omlish 0.0.0.dev191__py3-none-any.whl → 0.0.0.dev193__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
omlish/.manifests.json CHANGED
@@ -51,6 +51,20 @@
51
51
  }
52
52
  }
53
53
  },
54
+ {
55
+ "module": ".formats.ini.codec",
56
+ "attr": "_INI_LAZY_CODEC",
57
+ "file": "omlish/formats/ini/codec.py",
58
+ "line": 25,
59
+ "value": {
60
+ "$.codecs.base.LazyLoadedCodec": {
61
+ "mod_name": "omlish.formats.ini.codec",
62
+ "attr_name": "INI_CODEC",
63
+ "name": "ini",
64
+ "aliases": null
65
+ }
66
+ }
67
+ },
54
68
  {
55
69
  "module": ".formats.json.codecs",
56
70
  "attr": "_JSON_LAZY_CODEC",
@@ -136,13 +150,13 @@
136
150
  }
137
151
  },
138
152
  {
139
- "module": ".formats.toml",
153
+ "module": ".formats.toml.codec",
140
154
  "attr": "_TOML_LAZY_CODEC",
141
- "file": "omlish/formats/toml.py",
155
+ "file": "omlish/formats/toml/codec.py",
142
156
  "line": 16,
143
157
  "value": {
144
158
  "$.codecs.base.LazyLoadedCodec": {
145
- "mod_name": "omlish.formats.toml",
159
+ "mod_name": "omlish.formats.toml.codec",
146
160
  "attr_name": "TOML_CODEC",
147
161
  "name": "toml",
148
162
  "aliases": null
omlish/__about__.py CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev191'
2
- __revision__ = '624c4595fba1d5f4aef5328f7b9e24f6e09223f5'
1
+ __version__ = '0.0.0.dev193'
2
+ __revision__ = 'abb15c34774729bc05f56f8b60e9ee7fdc3b3526'
3
3
 
4
4
 
5
5
  #
omlish/codecs/base.py CHANGED
@@ -1,6 +1,8 @@
1
1
  """
2
2
  TODO:
3
3
  - bytes-like - bytearray, memoryview
4
+ - FileCodec
5
+ - implement options
4
6
  """
5
7
  import abc
6
8
  import typing as ta
@@ -1,5 +0,0 @@
1
- from .classes import ( # noqa
2
- Config,
3
- Configurable,
4
- get_impl,
5
- )
@@ -1,32 +1,33 @@
1
+ # ruff: noqa: UP006 UP007
2
+ # @omlish-lite
1
3
  import abc
2
- import itertools
3
4
  import typing as ta
4
5
 
5
- from .. import check
6
- from .. import lang
6
+ from ..lite.check import check
7
7
 
8
8
 
9
9
  K = ta.TypeVar('K')
10
10
  V = ta.TypeVar('V')
11
- StrMap = ta.Mapping[str, ta.Any]
12
11
 
13
12
 
14
- class _MISSING(lang.Marker):
15
- pass
13
+ ##
16
14
 
17
15
 
18
- class Flattening:
19
-
16
+ class ConfigFlattening:
20
17
  DEFAULT_DELIMITER = '.'
21
18
  DEFAULT_INDEX_OPEN = '('
22
19
  DEFAULT_INDEX_CLOSE = ')'
23
20
 
21
+ class _MISSING:
22
+ def __new__(cls, *args, **kwargs): # noqa
23
+ raise TypeError
24
+
24
25
  def __init__(
25
26
  self,
26
27
  *,
27
- delimiter=DEFAULT_DELIMITER,
28
- index_open=DEFAULT_INDEX_OPEN,
29
- index_close=DEFAULT_INDEX_CLOSE,
28
+ delimiter: str = DEFAULT_DELIMITER,
29
+ index_open: str = DEFAULT_INDEX_OPEN,
30
+ index_close: str = DEFAULT_INDEX_CLOSE,
30
31
  ) -> None:
31
32
  super().__init__()
32
33
 
@@ -34,8 +35,8 @@ class Flattening:
34
35
  self._index_open = check.not_empty(index_open)
35
36
  self._index_close = check.not_empty(index_close)
36
37
 
37
- def flatten(self, unflattened: StrMap) -> StrMap:
38
- def rec(prefix: list[str], value: ta.Any) -> None:
38
+ def flatten(self, unflattened: ta.Mapping[str, ta.Any]) -> ta.Mapping[str, ta.Any]:
39
+ def rec(prefix: ta.List[str], value: ta.Any) -> None:
39
40
  if isinstance(value, dict):
40
41
  for k, v in value.items():
41
42
  rec([*prefix, k], v)
@@ -53,8 +54,7 @@ class Flattening:
53
54
  rec([], unflattened)
54
55
  return ret
55
56
 
56
- class UnflattenNode(lang.Abstract, ta.Generic[K]):
57
-
57
+ class UnflattenNode(abc.ABC, ta.Generic[K]):
58
58
  @abc.abstractmethod
59
59
  def get(self, key: K) -> ta.Any:
60
60
  raise NotImplementedError
@@ -65,7 +65,7 @@ class Flattening:
65
65
 
66
66
  def setdefault(self, key: K, supplier: ta.Callable[[], V]) -> V:
67
67
  ret = self.get(key)
68
- if ret is _MISSING:
68
+ if ret is ConfigFlattening._MISSING:
69
69
  ret = supplier()
70
70
  self.put(key, ret)
71
71
  return ret
@@ -77,50 +77,48 @@ class Flattening:
77
77
  @staticmethod
78
78
  def maybe_build(value: ta.Any) -> ta.Any:
79
79
  check.not_none(value)
80
- return value.build() if isinstance(value, Flattening.UnflattenNode) else value
80
+ return value.build() if isinstance(value, ConfigFlattening.UnflattenNode) else value
81
81
 
82
82
  class UnflattenDict(UnflattenNode[str]):
83
-
84
83
  def __init__(self) -> None:
85
84
  super().__init__()
86
85
 
87
86
  self._dict: dict[str, ta.Any] = {}
88
87
 
89
88
  def get(self, key: str) -> ta.Any:
90
- return self._dict.get(key, _MISSING)
89
+ return self._dict.get(key, ConfigFlattening._MISSING)
91
90
 
92
91
  def put(self, key: str, value: ta.Any) -> None:
93
92
  check.arg(key not in self._dict)
94
93
  self._dict[key] = value
95
94
 
96
95
  def build(self) -> ta.Any:
97
- return {k: Flattening.UnflattenNode.maybe_build(v) for k, v in self._dict.items()}
96
+ return {k: ConfigFlattening.UnflattenNode.maybe_build(v) for k, v in self._dict.items()}
98
97
 
99
98
  class UnflattenList(UnflattenNode[int]):
100
-
101
99
  def __init__(self) -> None:
102
100
  super().__init__()
103
101
 
104
- self._list: list[ta.Any] = []
102
+ self._list: ta.List[ta.Any] = []
105
103
 
106
104
  def get(self, key: int) -> ta.Any:
107
105
  check.arg(key >= 0)
108
- return self._list[key] if key < len(self._list) else _MISSING
106
+ return self._list[key] if key < len(self._list) else ConfigFlattening._MISSING
109
107
 
110
108
  def put(self, key: int, value: ta.Any) -> None:
111
109
  check.arg(key >= 0)
112
110
  if key >= len(self._list):
113
- self._list.extend([_MISSING] * (key - len(self._list) + 1))
114
- check.arg(self._list[key] is _MISSING)
111
+ self._list.extend([ConfigFlattening._MISSING] * (key - len(self._list) + 1))
112
+ check.arg(self._list[key] is ConfigFlattening._MISSING)
115
113
  self._list[key] = value
116
114
 
117
115
  def build(self) -> ta.Any:
118
- return [Flattening.UnflattenNode.maybe_build(e) for e in self._list]
116
+ return [ConfigFlattening.UnflattenNode.maybe_build(e) for e in self._list]
119
117
 
120
- def unflatten(self, flattened: StrMap) -> StrMap:
121
- root = Flattening.UnflattenDict()
118
+ def unflatten(self, flattened: ta.Mapping[str, ta.Any]) -> ta.Mapping[str, ta.Any]:
119
+ root = ConfigFlattening.UnflattenDict()
122
120
 
123
- def split_keys(fkey: str) -> ta.Iterable[str | int]:
121
+ def split_keys(fkey: str) -> ta.Iterable[ta.Union[str, int]]:
124
122
  for part in fkey.split(self._delimiter):
125
123
  if self._index_open in part:
126
124
  check.state(part.endswith(self._index_close))
@@ -134,13 +132,13 @@ class Flattening:
134
132
  yield part
135
133
 
136
134
  for fk, v in flattened.items():
137
- node: Flattening.UnflattenNode = root
135
+ node: ConfigFlattening.UnflattenNode = root
138
136
  fks = list(split_keys(fk))
139
- for key, nkey in itertools.pairwise(fks):
137
+ for key, nkey in zip(fks, fks[1:]): # noqa
140
138
  if isinstance(nkey, str):
141
- node = node.setdefault(key, Flattening.UnflattenDict)
139
+ node = node.setdefault(key, ConfigFlattening.UnflattenDict)
142
140
  elif isinstance(nkey, int):
143
- node = node.setdefault(key, Flattening.UnflattenList)
141
+ node = node.setdefault(key, ConfigFlattening.UnflattenList)
144
142
  else:
145
143
  raise TypeError(key)
146
144
  node.put(fks[-1], v)
omlish/configs/strings.py CHANGED
@@ -88,9 +88,9 @@ def interpolate_strings(v: T, rpl: ta.Mapping[str, str]) -> T:
88
88
  def fn(v):
89
89
  if not v:
90
90
  return v
91
- sps = glyphsplit.split_braces(v)
91
+ sps = glyphsplit.glyph_split_braces(v)
92
92
  if len(sps) == 1 and isinstance(sps[0], str):
93
93
  return sps[0]
94
- return ''.join(rpl[p.s] if isinstance(p, glyphsplit.GlyphMatch) else p for p in sps)
94
+ return ''.join(rpl[p.s] if isinstance(p, glyphsplit.GlyphSplitMatch) else p for p in sps)
95
95
 
96
96
  return StringRewriter(fn)(v)
@@ -0,0 +1,5 @@
1
+ """
2
+ TODO:
3
+ - csv
4
+ - ini
5
+ """
File without changes
@@ -0,0 +1,26 @@
1
+ import configparser
2
+
3
+ from ..codecs import make_object_lazy_loaded_codec
4
+ from ..codecs import make_str_object_codec
5
+ from .sections import IniSectionSettingsMap
6
+ from .sections import extract_ini_sections
7
+ from .sections import render_ini_sections
8
+
9
+
10
+ ##
11
+
12
+
13
+ def loads(s: str) -> IniSectionSettingsMap:
14
+ cp = configparser.ConfigParser()
15
+ cp.read_string(s)
16
+ return extract_ini_sections(cp)
17
+
18
+
19
+ def dumps(sm: IniSectionSettingsMap) -> str:
20
+ return render_ini_sections(sm)
21
+
22
+
23
+ INI_CODEC = make_str_object_codec('ini', dumps, loads)
24
+
25
+ # @omlish-manifest
26
+ _INI_LAZY_CODEC = make_object_lazy_loaded_codec(__name__, 'INI_CODEC', INI_CODEC)
@@ -0,0 +1,45 @@
1
+ # ruff: noqa: UP006 UP007
2
+ # @omlish-lite
3
+ import configparser
4
+ import io
5
+ import typing as ta
6
+
7
+
8
+ IniSectionSettingsMap = ta.Mapping[str, ta.Mapping[str, ta.Union[str, ta.Sequence[str]]]] # ta.TypeAlias
9
+
10
+
11
+ ##
12
+
13
+
14
+ def extract_ini_sections(cp: configparser.ConfigParser) -> IniSectionSettingsMap:
15
+ config_dct: ta.Dict[str, ta.Any] = {}
16
+ for sec in cp.sections():
17
+ cd = config_dct
18
+ for k in sec.split('.'):
19
+ cd = cd.setdefault(k, {})
20
+ cd.update(cp.items(sec))
21
+ return config_dct
22
+
23
+
24
+ ##
25
+
26
+
27
+ def render_ini_sections(
28
+ settings_by_section: IniSectionSettingsMap,
29
+ ) -> str:
30
+ out = io.StringIO()
31
+
32
+ for i, (section, settings) in enumerate(settings_by_section.items()):
33
+ if i:
34
+ out.write('\n')
35
+
36
+ out.write(f'[{section}]\n')
37
+
38
+ for k, v in settings.items():
39
+ if isinstance(v, str):
40
+ out.write(f'{k}={v}\n')
41
+ else:
42
+ for vv in v:
43
+ out.write(f'{k}={vv}\n')
44
+
45
+ return out.getvalue()
File without changes
@@ -1,7 +1,7 @@
1
1
  import tomllib
2
2
 
3
- from .codecs import make_object_lazy_loaded_codec
4
- from .codecs import make_str_object_codec
3
+ from ..codecs import make_object_lazy_loaded_codec
4
+ from ..codecs import make_str_object_codec
5
5
 
6
6
 
7
7
  ##