class Configuration(object): """Helper class that manages configuration values in a INI configuration file. """ reload_signal = signals.signal( 'config-changed', u'This signal will be emitted everytime the configuration will go' u' through the reloading process') defined_vars = {} def __init__(self, filename, defaults=None): self.filename = filename self._values = {} self._converted_values = {} self._lock = Lock() with self._lock: self._load_config() def _load_config(self): # if the path does not exist yet set the existing flag to none and # set the time timetamp for the filename to something in the past if not path.exists(self.filename): self.exists = False self._load_time = 0 return # otherwise parse the file and copy all values into the internal # values dict. Do that also for values not covered by the current # `defined_vars` dict to preserve variables of disabled plugins self._load_time = path.getmtime(self.filename) self.exists = True section = 'inyoka' with open(self.filename) as fobj: for line in fobj: line = line.strip() if not line or line[0] in '#;': continue elif line[0] == '[' and line[-1] == ']': section = line[1:-1].strip() section = section.rstrip(u'.') elif '=' not in line: key = line.strip() value = '' else: key, value = line.split('=', 1) key = key.strip() if section != 'inyoka': if not section.endswith('.'): section += '.' key = section + key self._values[key] = unquote_value(value.strip()) def __getitem__(self, key): """Return the value for a key.""" try: return self._converted_values[key] except KeyError: field = self.defined_vars[key] try: value = from_string(self._values[key], field) except KeyError: value = field.get_default() self._converted_values[key] = value return value def __setitem__(self, key, value): """Set the config item's value. May raise `IOError`, you may want to use `change_single`.""" self.change_single(key, value, False) def __delitem__(self, key): """Revert the config item's value to its default. May raise `IOError`, you may want to use `revert_single`""" self.revert_single(key, False) def change_single(self, key, value, silent=False): """Create and commit a transaction fro a single key-value pair. Return `True` on success, otherwise `False`. If :attr:`silent` is applied `True` we fail silently on exceptions. """ trans = self.edit() try: trans[key] = value trans.commit() except IOError: if silent: return False raise return True def revert_single(self, key, silent=False): """Revert a single key to it's default. Fail silently if :attr:`silent` is applied `True`, see :meth:`change_single` for more details. """ trans = self.edit() try: trans.revert_to_default(key) trans.commit() except IOError: if silent: return False raise return True def edit(self): """Return a new transaction object.""" return ConfigTransaction(self) def touch(self): """Touch the file to trigger a reload.""" os.utime(self.filename, None) def reload(self): with self._lock: self._values = {} self._converted_values = {} self._load_config() Configuration.reload_signal.send('config-changed', config=self) return self @property def changed_external(self): """True if there are changes on the file system.""" if not path.isfile(self.filename): return False return path.getmtime(self.filename) > self._load_time def __iter__(self): """Iterate over all keys""" return iter(self.defined_vars) iterkeys = __iter__ def __contains__(self, key): """Check if a given key exists.""" return key in self.defined_vars def itersection(self, section): """Iterate over all values.""" for key in self: if key.startswith(section): yield key, self[key] def itervalues(self, section=None): """Iterate over all values.""" for key in self.iterkeys(): yield self[key] def iteritems(self): """Iterate over all keys and values.""" for key in self: yield key, self[key] def values(self): """Return a list of values.""" return list(self.itervalues()) def keys(self): """Return a list of keys.""" return list(self) def items(self): """Return a list of all key, value tuples.""" return list(self.iteritems()) def __len__(self): return len(self.defined_vars) def __repr__(self): return '<%s %r>' % (self.__class__.__name__, dict(self.items()))
from os.path import realpath, dirname from gettext import NullTranslations from weakref import WeakKeyDictionary from babel import Locale, UnknownLocaleError from babel.support import Translations as TranslationsBase, LazyProxy from inyoka.context import ctx from inyoka.signals import signals from inyoka.core.config import TextConfigField __all__ = ['_', 'gettext', 'ngettext', 'lazy_gettext', 'lazy_ngettext'] _translations = None _js_translations = WeakKeyDictionary() translations_reloaded = signals.signal('translations-reloaded') language = TextConfigField('language', u'en') def load_core_translations(locale): """Return the matching locale catalog for `locale`""" global _translations base = realpath(dirname(__file__)) ret = _translations = Translations.load(base, locale) return ret @ctx.cfg.reload_signal.connect def reload_translations(sender, config):
from jinja2 import Environment, FileSystemLoader, StrictUndefined, \ ChoiceLoader, FileSystemBytecodeCache, MemcachedBytecodeCache, \ PrefixLoader from inyoka import INYOKA_REVISION, l10n, i18n from inyoka.context import ctx from inyoka.signals import signals from inyoka.core.http import Response from inyoka.core.routing import href, IServiceProvider from inyoka.core.resource import IResourceManager from inyoka.core.cache import cache as inyoka_cache from inyoka.core.config import TextConfigField, BooleanConfigField #! This signal is raised if a template is rendered. Use it to catch context variables #! and such stuff. template_rendered = signals.signal('template-rendered') #: The default templates path _default_templates_path = os.path.join(os.environ['INYOKA_MODULE'], 'templates') #: Custom template path which is searched before the default path templates_path = TextConfigField('templates.path', default=_default_templates_path) #: Auto reload template files if they changed templates_auto_reload = BooleanConfigField('templates.auto_reload', default=True) #: Use either ’memory’, ’filesystem’, or ’memcached’ bytecode caches templates_use_cache = BooleanConfigField('templates.use_cache', default=False) #: Use memcached for bytecode caching templates_use_memcached_cache = BooleanConfigField('templates.use_memcached_cache', default=False)