diff --git a/r2/r2/config/environment.py b/r2/r2/config/environment.py index 32a6f764b..98058ea5d 100644 --- a/r2/r2/config/environment.py +++ b/r2/r2/config/environment.py @@ -30,7 +30,8 @@ mimetypes.init() import webhelpers from r2.config import routing -from r2.lib.app_globals import ConfigValue, Globals +from r2.lib.app_globals import Globals +from r2.lib.configparse import ConfigValue from r2.lib import rpc import r2.lib.helpers from r2.lib.plugin import PluginLoader diff --git a/r2/r2/lib/app_globals.py b/r2/r2/lib/app_globals.py index 716f65341..5b91b25ba 100755 --- a/r2/r2/lib/app_globals.py +++ b/r2/r2/lib/app_globals.py @@ -28,6 +28,7 @@ from urlparse import urlparse import json from sqlalchemy import engine from sqlalchemy import event +from r2.lib.configparse import ConfigValue, ConfigValueParser from r2.lib.cache import LocalCache, SelfEmptyingCache from r2.lib.cache import CMemcache, StaleCacheChain from r2.lib.cache import HardCache, MemcacheChain, MemcacheChain, HardcacheChain @@ -39,62 +40,6 @@ from r2.lib.lock import make_lock_factory from r2.lib.manager import db_manager from r2.lib.stats import Stats, CacheStats, StatsCollectingConnectionPool -class ConfigValue(object): - @staticmethod - def int(v, key=None, data=None): - return int(v) - - @staticmethod - def float(v, key=None, data=None): - return float(v) - - @staticmethod - def bool(v, key=None, data=None): - return (v.lower() == 'true') if v else None - - @staticmethod - def tuple(v, key=None, data=None): - return tuple(ConfigValue.to_iter(v)) - - @staticmethod - def choice(v, key, data): - if v not in data: - raise ValueError("Unknown option for %r: %r not in %r" % (key, v, data)) - return data[v] - - @staticmethod - def to_iter(v, delim = ','): - return (x.strip() for x in v.split(delim) if x) - -class ConfigValueParser(dict): - def __init__(self, raw_data): - dict.__init__(self, raw_data) - self.config_keys = {} - self.raw_data = raw_data - - def add_spec(self, spec): - new_keys = [] - for parser, keys in spec.iteritems(): - # keys can be either a list or a dict - for key in keys: - assert key not in self.config_keys - # if keys is a dict, the value is passed as extra data to the parser. - extra_data = keys[key] if type(keys) is dict else None - self.config_keys[key] = (parser, extra_data) - new_keys.append(key) - self._update_values(new_keys) - - def _update_values(self, keys): - for key in keys: - if key not in self.raw_data: - continue - - value = self.raw_data[key] - if key in self.config_keys: - parser, extra_data = self.config_keys[key] - value = parser(value, key, extra_data) - self[key] = value - class Globals(object): spec = { diff --git a/r2/r2/lib/configparse.py b/r2/r2/lib/configparse.py new file mode 100644 index 000000000..79a59d235 --- /dev/null +++ b/r2/r2/lib/configparse.py @@ -0,0 +1,77 @@ +# The contents of this file are subject to the Common Public Attribution +# License Version 1.0. (the "License"); you may not use this file except in +# compliance with the License. You may obtain a copy of the License at +# http://code.reddit.com/LICENSE. The License is based on the Mozilla Public +# License Version 1.1, but Sections 14 and 15 have been added to cover use of +# software over a computer network and provide for limited attribution for the +# Original Developer. In addition, Exhibit A has been modified to be consistent +# with Exhibit B. +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +# the specific language governing rights and limitations under the License. +# +# The Original Code is Reddit. +# +# The Original Developer is the Initial Developer. The Initial Developer of the +# Original Code is CondeNet, Inc. +# +# All portions of the code written by CondeNet are Copyright (c) 2006-2010 +# CondeNet, Inc. All Rights Reserved. +################################################################################ + +class ConfigValue(object): + @staticmethod + def int(v, key=None, data=None): + return int(v) + + @staticmethod + def float(v, key=None, data=None): + return float(v) + + @staticmethod + def bool(v, key=None, data=None): + return (v.lower() == 'true') if v else None + + @staticmethod + def tuple(v, key=None, data=None): + return tuple(ConfigValue.to_iter(v)) + + @staticmethod + def choice(v, key, data): + if v not in data: + raise ValueError("Unknown option for %r: %r not in %r" % (key, v, data)) + return data[v] + + @staticmethod + def to_iter(v, delim = ','): + return (x.strip() for x in v.split(delim) if x) + +class ConfigValueParser(dict): + def __init__(self, raw_data): + dict.__init__(self, raw_data) + self.config_keys = {} + self.raw_data = raw_data + + def add_spec(self, spec): + new_keys = [] + for parser, keys in spec.iteritems(): + # keys can be either a list or a dict + for key in keys: + assert key not in self.config_keys + # if keys is a dict, the value is passed as extra data to the parser. + extra_data = keys[key] if type(keys) is dict else None + self.config_keys[key] = (parser, extra_data) + new_keys.append(key) + self._update_values(new_keys) + + def _update_values(self, keys): + for key in keys: + if key not in self.raw_data: + continue + + value = self.raw_data[key] + if key in self.config_keys: + parser, extra_data = self.config_keys[key] + value = parser(value, key, extra_data) + self[key] = value