1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- # coding: utf-8
- import typing
-
- import re
-
- import yaml
-
- from synergine2.exceptions import SynergineException
-
- DEFAULT_VALUE = '__DEFAULT_VALUE__'
-
-
- class Config(dict):
- def __init__(
- self,
- seq: typing.Union[dict, None]=None,
- **kwargs: typing.Any
- ) -> None:
- seq = seq or {}
- super().__init__(seq, **kwargs)
- """
- Regular expression used to find key access, example of matching
- strings:
- * foo[0]
- * bar.buz[1]
- Not working strings (see blsi.common.config.Config#get TODO):
- * bad[0][1]
-
- Literal translation of expression is:
- * Group "(.+)" Everything with minimum 1 char
- * Group "(\[([0-9])+\])" numeric number into brackets
- """
- self._index_re = re.compile(r'(.+)(\[([0-9])+\])')
-
- def resolve(
- self,
- k: str,
- d: object=DEFAULT_VALUE,
- ) -> typing.Union[None, str, float, int, bool, dict, list]:
- """
- Allow to get dict value with following expression:
- config.get('foo[0].bar.baz'), so '.' for dict keys, and [x] for
- list index.
- TODO BS 20170124: Actually don't work with multiple indexes "foo[0][0]"
- :param k: key
- :param d: default value
- :return:
- """
- if '.' in k:
- try:
- parts = k.split('.')
- value = self
- for part in parts:
- index_search = re.search(self._index_re, part)
- if index_search is not None:
- groups = index_search.groups()
- part = groups[0]
- index = int(groups[2])
- value = value.get(part) # type: ignore
- value = value[index]
- else:
- value = value.get(part, d) # type: ignore
- return value
- except IndexError:
- value = d # type: ignore
- except KeyError:
- value = d # type: ignore
- except AttributeError:
- value = d # type: ignore
-
- if value == DEFAULT_VALUE:
- raise SynergineException(
- 'No configuration found for "{}"'.format(k)
- )
- elif value == DEFAULT_VALUE:
- return None
-
- return value
- else:
-
- value = super().get(k, d)
-
- if value == DEFAULT_VALUE:
- raise SynergineException(
- 'No configuration found for "{}"'.format(k)
- )
- elif value == DEFAULT_VALUE:
- return None
-
- return value
-
- def load_yaml(self, yaml_file_path) -> None:
- with open(yaml_file_path, 'r') as yaml_file:
- self.update(yaml.load(yaml_file))
|