def test_get_items_with_key_prefix_from_sequence(self): items = [ ('a.a', 1), ('a.b', 2), ('b.a', 1), ('b.b', 2), ] items_with_prefix = util.get_items_with_key_prefix(items, 'a.') expected = [('a', 1), ('b', 2)] self.assertEqual(items_with_prefix, expected)
def test_get_items_with_key_prefix(self): items = { 'a.a': 1, 'a.b': 2, 'b.a': 1, 'b.b': 2, } items_with_prefix = util.get_items_with_key_prefix(items, 'a.') expected = {'a': 1, 'b': 2} self.assertEqual(items_with_prefix, expected)
def parse_settings(settings, conversion_map={}, defaults={}, required=(), prefix=None, strip_prefix=True): """Convert the values of ``settings``. To convert only a subset of the settings, pass ``prefix``; only the settings with a key matching ``prefix`` will be returned (see :func:`get_items_with_key_prefix` for details). Settings passed via ``defaults`` will be added if they're not already present in ``settings`` (and they'll be converted too). Required fields can be listed in ``required``. If any required fields are missing, a ``ValueError`` will be raised. For each setting... - If the key for the setting specifies a converter via the ``(converter)key`` syntax, the specified converter will be called to convert its value (the converter must be a builtin or a function from :mod:`tangled.converters`). - If the key for the setting is in ``conversion_map``, the function it maps to will be used to convert its value. - If the special key '*' is in ``conversion_map``, the function it maps to will be used to convert the setting. - Otherwise, the value will be used as is (i.e., as a string). The original ``settings`` dict will not be changed. """ parsed_settings = {} if prefix is not None: settings = get_items_with_key_prefix(settings, prefix, strip_prefix) for k, v in defaults.items(): settings.setdefault(k, v) for k, v in settings.items(): if isinstance(v, str): match = CONVERTER_KEY_RE.search(k) if match: k = match.group('k') converter = match.group('converter') converter = converters.get_converter(converter) elif k in conversion_map: converter = converters.get_converter(conversion_map[k]) elif '*' in conversion_map: converter = converters.get_converter(conversion_map['*']) else: converter = lambda v: v v = converter(v) parsed_settings[k] = v if required: check_required(parsed_settings, required) return parsed_settings
def get_settings(self, settings=None, prefix='tangled.app.', **kwargs): """Get settings with names that start with ``prefix``. This is a front end for :func:`tangled.util.get_items_with_key_prefix` that sets defaults for ``settings`` and ``prefix``. By default, this will get the settings from ``self.settings`` that have a ``'tangled.app.'`` prefix. Alternate ``settings`` and/or ``prefix`` can be specified. """ if settings is None: settings = self.settings return get_items_with_key_prefix(settings, prefix, **kwargs)
def parse_settings(settings, defaults={}, required=(), extra={}, prefix=None, strip_prefix=True): """Convert settings values. All settings values should be JSON-encoded strings. For example:: debug = true factory:object = "tangled.web:Application" something:package.module:SomeClass = "value" Settings passed via ``defaults`` will be added if they're not already present in ``settings``. To convert only a subset of the settings, pass ``prefix``; only the settings with a key matching ``prefix`` will be returned (see :func:`get_items_with_key_prefix` for details). Required fields can be listed in ``required``. If any required fields are missing, a ``ValueError`` will be raised. For each setting: - If the key specifies a type using ``key:type`` syntax, the specified type will be used to parse the value. The type can refer to any callable that accepts a single string. If the type is specified as ``object``, :func:`.load_object()` will be used to parse the value. The ``:type`` will be stripped from the key. - Otherwise, the value will be passed to ``json.loads()``. The original ``settings`` dict will not be modified. """ loads = json.loads parsed_settings = {} parsed_settings.update(defaults) if prefix is not None: settings = get_items_with_key_prefix(settings, prefix, strip_prefix) for key, value in settings.items(): value = value.strip() if not value: value = None else: key, *rest = key.split(':', 1) try: value = loads(value) except ValueError: message = 'Could not parse JSON value for {key}'.format(key=key) raise ValueError(message) from None if rest: kind = get_type(rest[0]) value = kind(value) parsed_settings[key] = value parsed_settings.update(extra) if required: check_required(parsed_settings, required) return parsed_settings
def parse_settings(settings, defaults={}, required=(), extra={}, prefix=None, strip_prefix=True): """Convert settings values. All settings values should be JSON-encoded strings. For example:: debug = true factory:object = "tangled.web:Application" something:package.module:SomeClass = "value" Settings passed via ``defaults`` will be added if they're not already present in ``settings``. To convert only a subset of the settings, pass ``prefix``; only the settings with a key matching ``prefix`` will be returned (see :func:`get_items_with_key_prefix` for details). Required fields can be listed in ``required``. If any required fields are missing, a ``ValueError`` will be raised. For each setting: - If the key specifies a type using ``key:type`` syntax, the specified type will be used to parse the value. The type can refer to any callable that accepts a single string. If the type is specified as ``object``, :func:`.load_object()` will be used to parse the value. The ``:type`` will be stripped from the key. - Otherwise, the value will be passed to ``json.loads()``. The original ``settings`` dict will not be modified. """ loads = json.loads parsed_settings = {} parsed_settings.update(defaults) if prefix is not None: settings = get_items_with_key_prefix(settings, prefix, strip_prefix) for key, value in settings.items(): value = value.strip() if not value: value = None else: key, *rest = key.split(':', 1) try: value = loads(value) except ValueError: message = 'Could not parse JSON value for {key}'.format( key=key) raise ValueError(message) from None if rest: kind = get_type(rest[0]) value = kind(value) parsed_settings[key] = value parsed_settings.update(extra) if required: check_required(parsed_settings, required) return parsed_settings