| # -*- coding: utf-8 -*- |
| """ |
| webapp2_extras.config |
| ===================== |
| |
| Configuration object for webapp2. |
| |
| This module is deprecated. See :class:`webapp2.WSGIApplication.config`. |
| |
| :copyright: 2011 by tipfy.org. |
| :license: Apache Sotware License, see LICENSE for details. |
| """ |
| from __future__ import absolute_import |
| |
| import warnings |
| |
| import webapp2 |
| |
| warnings.warn(DeprecationWarning( |
| 'webapp2_extras.config is deprecated. ' |
| 'The WSGIApplication uses webapp2.Config instead.'), |
| stacklevel=1) |
| |
| #: Value used for missing default values. |
| DEFAULT_VALUE = object() |
| |
| #: Value used for required values. |
| REQUIRED_VALUE = object() |
| |
| |
| class Config(dict): |
| """A simple configuration dictionary keyed by module name. This is a |
| dictionary of dictionaries. It requires all values to be dictionaries |
| and applies updates and default values to the inner dictionaries instead |
| of the first level one. |
| |
| The configuration object can be set as a ``config`` attribute of |
| :class:`WSGIApplication`:: |
| |
| import webapp2 |
| from webapp2_extras import config as webapp2_config |
| |
| my_config = {} |
| |
| my_config['my.module'] = { |
| 'foo': 'bar', |
| } |
| |
| app = webapp2.WSGIApplication(routes=[ |
| webapp2.Route('/', name='home', handler=MyHandler) |
| ]) |
| app.config = webapp2_config.Config(my_config) |
| |
| Then to read configuration values, get them from the app:: |
| |
| class MyHandler(RequestHandler): |
| def get(self): |
| foo = self.app.config['my.module']['foo'] |
| |
| # ... |
| """ |
| #: Loaded module configurations. |
| loaded = None |
| |
| def __init__(self, values=None, defaults=None): |
| """Initializes the configuration object. |
| |
| :param values: |
| A dictionary of configuration dictionaries for modules. |
| :param defaults: |
| A dictionary of configuration dictionaries for initial default |
| values. These modules are marked as loaded. |
| """ |
| self.loaded = [] |
| if values is not None: |
| assert isinstance(values, dict) |
| for module, config in values.iteritems(): |
| self.update(module, config) |
| |
| if defaults is not None: |
| assert isinstance(defaults, dict) |
| for module, config in defaults.iteritems(): |
| self.setdefault(module, config) |
| self.loaded.append(module) |
| |
| def __getitem__(self, module): |
| """Returns the configuration for a module. If it is not already |
| set, loads a ``default_config`` variable from the given module and |
| updates the configuration with those default values |
| |
| Every module that allows some kind of configuration sets a |
| ``default_config`` global variable that is loaded by this function, |
| cached and used in case the requested configuration was not defined |
| by the user. |
| |
| :param module: |
| The module name. |
| :returns: |
| A configuration value. |
| """ |
| if module not in self.loaded: |
| # Load default configuration and update config. |
| values = webapp2.import_string(module + '.default_config', |
| silent=True) |
| if values: |
| self.setdefault(module, values) |
| |
| self.loaded.append(module) |
| |
| try: |
| return dict.__getitem__(self, module) |
| except KeyError: |
| raise KeyError('Module %r is not configured.' % module) |
| |
| def __setitem__(self, module, values): |
| """Sets a configuration for a module, requiring it to be a dictionary. |
| |
| :param module: |
| A module name for the configuration, e.g.: `webapp2.ext.i18n`. |
| :param values: |
| A dictionary of configurations for the module. |
| """ |
| assert isinstance(values, dict), 'Module configuration must be a dict.' |
| dict.__setitem__(self, module, SubConfig(module, values)) |
| |
| def get(self, module, default=DEFAULT_VALUE): |
| """Returns a configuration for a module. If default is not provided, |
| returns an empty dict if the module is not configured. |
| |
| :param module: |
| The module name. |
| :params default: |
| Default value to return if the module is not configured. If not |
| set, returns an empty dict. |
| :returns: |
| A module configuration. |
| """ |
| if default is DEFAULT_VALUE: |
| default = {} |
| |
| return dict.get(self, module, default) |
| |
| def setdefault(self, module, values): |
| """Sets a default configuration dictionary for a module. |
| |
| :param module: |
| The module to set default configuration, e.g.: `webapp2.ext.i18n`. |
| :param values: |
| A dictionary of configurations for the module. |
| :returns: |
| The module configuration dictionary. |
| """ |
| assert isinstance(values, dict), 'Module configuration must be a dict.' |
| if module not in self: |
| dict.__setitem__(self, module, SubConfig(module)) |
| |
| module_dict = dict.__getitem__(self, module) |
| |
| for key, value in values.iteritems(): |
| module_dict.setdefault(key, value) |
| |
| return module_dict |
| |
| def update(self, module, values): |
| """Updates the configuration dictionary for a module. |
| |
| :param module: |
| The module to update the configuration, e.g.: `webapp2.ext.i18n`. |
| :param values: |
| A dictionary of configurations for the module. |
| """ |
| assert isinstance(values, dict), 'Module configuration must be a dict.' |
| if module not in self: |
| dict.__setitem__(self, module, SubConfig(module)) |
| |
| dict.__getitem__(self, module).update(values) |
| |
| def get_config(self, module, key=None, default=REQUIRED_VALUE): |
| """Returns a configuration value for a module and optionally a key. |
| Will raise a KeyError if they the module is not configured or the key |
| doesn't exist and a default is not provided. |
| |
| :param module: |
| The module name. |
| :params key: |
| The configuration key. |
| :param default: |
| Default value to return if the key doesn't exist. |
| :returns: |
| A module configuration. |
| """ |
| module_dict = self.__getitem__(module) |
| |
| if key is None: |
| return module_dict |
| |
| return module_dict.get(key, default) |
| |
| |
| class SubConfig(dict): |
| def __init__(self, module, values=None): |
| dict.__init__(self, values or ()) |
| self.module = module |
| |
| def __getitem__(self, key): |
| try: |
| value = dict.__getitem__(self, key) |
| except KeyError: |
| raise KeyError('Module %r does not have the config key %r' % |
| (self.module, key)) |
| |
| if value is REQUIRED_VALUE: |
| raise KeyError('Module %r requires the config key %r to be ' |
| 'set.' % (self.module, key)) |
| |
| return value |
| |
| def get(self, key, default=None): |
| if key not in self: |
| value = default |
| else: |
| value = dict.__getitem__(self, key) |
| |
| if value is REQUIRED_VALUE: |
| raise KeyError('Module %r requires the config key %r to be ' |
| 'set.' % (self.module, key)) |
| |
| return value |