123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- """
- The ConfigObj Extension provides configuration handling based on
- `configobj <http://www.voidspace.org.uk/python/configobj.html>`_. It is a
- drop-in replacement for the default config handler
- :class:`cement.ext.ext_configparser.ConfigParserConfigHandler`.
- One of the primary features of ConfigObj is that you can access the
- application configuration as a dictionary object.
- Requirements
- ------------
- * ConfigObj (``pip install configobj``)
- Configuration
- -------------
- This extension does not honor any application configuration settings.
- Usage
- -----
- .. code-block:: python
- from cement.core.foundation import CementApp
- class MyApp(CementApp):
- class Meta:
- label = 'myapp'
- extensions = ['configobj']
- config_handler = 'configobj'
- with MyApp() as app:
- app.run()
- # get a config setting
- app.config['myapp']['foo']
- # set a config setting
- app.config['myapp']['foo'] = 'bar2'
- # etc.
- """
- import os
- import sys
- from ..core import config, exc
- from ..utils.misc import minimal_logger
- from configobj import ConfigObj
- LOG = minimal_logger(__name__)
- class ConfigObjConfigHandler(config.CementConfigHandler, ConfigObj):
- """
- This class implements the :ref:`IConfig <cement.core.config>`
- interface, and sub-classes from `configobj.ConfigObj
- <http://www.voidspace.org.uk/python/configobj.html>`_,
- which is an external library and not included with Python. Please
- reference the ConfigObj documentation for full usage of the class.
- Arguments and keyword arguments are passed directly to ConfigObj
- on initialization.
- """
- class Meta:
- """Handler meta-data."""
- interface = config.IConfig
- label = 'configobj'
- def __init__(self, *args, **kw):
- super(ConfigObjConfigHandler, self).__init__(*args, **kw)
- self.app = None
- def _setup(self, app_obj):
- self.app = app_obj
- def get_sections(self):
- """
- Return a list of [section] that exist in the configuration.
- :returns: list
- """
- return self.sections
- def get_section_dict(self, section):
- """
- Return a dict representation of a section.
- :param section: The section of the configuration.
- I.e. ``[block_section]``
- :returns: dict
- """
- dict_obj = dict()
- for key in self.keys(section):
- dict_obj[key] = self.get(section, key)
- return dict_obj
- def _parse_file(self, file_path):
- """
- Parse a configuration file at `file_path` and store it.
- :param file_path: The file system path to the configuration file.
- :returns: boolean (True if file was read properly, False otherwise)
- """
- _c = ConfigObj(file_path)
- self.merge(_c.dict())
- # FIX ME: Should check that file was read properly, however if not it
- # will likely raise an exception anyhow.
- return True
- def keys(self, section):
- """
- Return a list of keys for a given section.
- :param section: The configuration [section].
- """
- return self[section].keys()
- def get(self, section, key):
- """
- Get a value for a given key under section.
- :param section: The configuration [section].
- :param key: The configuration key under the section.
- :returns: unknown (the value of the key)
- """
- return self[section][key]
- def set(self, section, key, value):
- """
- Set a configuration key value under [section].
- :param section: The configuration [section].
- :param key: The configuration key under the section.
- :param value: The value to set the key to.
- :returns: None
- """
- self[section][key] = value
- def has_section(self, section):
- """
- Return True/False whether the configuration [section] exists.
- :param section: The section to check for.
- :returns: bool
- """
- if section in self.get_sections():
- return True
- else:
- return False
- def add_section(self, section):
- """
- Add a section to the configuration.
- :param section: The configuration [section] to add.
- """
- if not self.has_section(section):
- self[section] = dict()
- def merge(self, dict_obj, override=True):
- """
- Merge a dictionary into our config. If override is True then
- existing config values are overridden by those passed in.
- :param dict_obj: A dictionary of configuration keys/values to merge
- into our existing config (self).
- :param override: Whether or not to override existing values in the
- config.
- :returns: None
- """
- for section in list(dict_obj.keys()):
- if type(dict_obj[section]) == dict:
- if section not in self.get_sections():
- self.add_section(section)
- for key in list(dict_obj[section].keys()):
- if override:
- self.set(section, key, dict_obj[section][key])
- else:
- # only set it if the key doesn't exist
- if key not in self.keys(section):
- self.set(section, key, dict_obj[section][key])
- # we don't support nested config blocks, so no need to go
- # further down to more nested dicts.
- def load(app):
- app.handler.register(ConfigObjConfigHandler)
|