Browse Source

replace Config object

Bastien Sevajol 6 years ago
parent
commit
7a895328b9
2 changed files with 85 additions and 4 deletions
  1. 0 1
      requirements.txt
  2. 85 3
      synergine2/config.py

+ 0 - 1
requirements.txt View File

@@ -9,7 +9,6 @@ packaging==16.8
9 9
 psutil==5.2.2
10 10
 py==1.4.31
11 11
 pyglet==1.2.4
12
-pymlconf==0.7.0
13 12
 pyparsing==2.1.10
14 13
 pytest==3.0.4
15 14
 pytest-cov==2.5.1

+ 85 - 3
synergine2/config.py View File

@@ -1,6 +1,88 @@
1 1
 # coding: utf-8
2
-from pymlconf import ConfigManager
2
+import typing
3 3
 
4
+import re
4 5
 
5
-class Config(ConfigManager):
6
-    pass
6
+from synergine2.exceptions import SynergineException
7
+
8
+DEFAULT_VALUE = '__DEFAULT_VALUE__'
9
+
10
+
11
+class Config(dict):
12
+    def __init__(
13
+            self,
14
+            seq: typing.Union[dict, None]=None,
15
+            **kwargs: typing.Any
16
+    ) -> None:
17
+        seq = seq or {}
18
+        super().__init__(seq, **kwargs)
19
+        """
20
+        Regular expression used to find key access, example of matching
21
+        strings:
22
+          * foo[0]
23
+          * bar.buz[1]
24
+        Not working strings (see blsi.common.config.Config#get TODO):
25
+          * bad[0][1]
26
+
27
+        Literal translation of expression is:
28
+          * Group "(.+)" Everything with minimum 1 char
29
+          * Group "(\[([0-9])+\])" numeric number into brackets
30
+        """
31
+        self._index_re = re.compile(r'(.+)(\[([0-9])+\])')
32
+
33
+    def resolve(
34
+        self,
35
+        k: str,
36
+        d: object=DEFAULT_VALUE,
37
+    ) -> typing.Union[None, str, float, int, bool, dict, list]:
38
+        """
39
+        Allow to get dict value with following expression:
40
+        config.get('foo[0].bar.baz'), so '.' for dict keys, and [x] for
41
+        list index.
42
+        TODO BS 20170124: Actually don't work with multiple indexes "foo[0][0]"
43
+        :param k: key
44
+        :param d: default value
45
+        :return:
46
+        """
47
+        if '.' in k:
48
+            try:
49
+                parts = k.split('.')
50
+                value = self
51
+                for part in parts:
52
+                    index_search = re.search(self._index_re, part)
53
+                    if index_search is not None:
54
+                        groups = index_search.groups()
55
+                        part = groups[0]
56
+                        index = int(groups[2])
57
+                        value = value.get(part)  # type: ignore
58
+                        value = value[index]
59
+                    else:
60
+                        value = value.get(part, d)  # type: ignore
61
+                return value
62
+            except IndexError:
63
+                value = d  # type: ignore
64
+            except KeyError:
65
+                value = d  # type: ignore
66
+            except AttributeError:
67
+                value = d  # type: ignore
68
+
69
+            if value == DEFAULT_VALUE:
70
+                raise SynergineException(
71
+                    'No configuration found for "{}"'.format(k)
72
+                )
73
+            elif value == DEFAULT_VALUE:
74
+                return None
75
+
76
+            return value
77
+        else:
78
+
79
+            value = super().get(k, d)
80
+
81
+            if value == DEFAULT_VALUE:
82
+                raise SynergineException(
83
+                    'No configuration found for "{}"'.format(k)
84
+                )
85
+            elif value == DEFAULT_VALUE:
86
+                return None
87
+
88
+            return value