Exemplo n.º 1
0
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()))
Exemplo n.º 2
0
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):
Exemplo n.º 3
0
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)