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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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.dev192'
2
- __revision__ = '75df1ba4f1cbe21d9930a1f467e7e99c5c23c621'
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
  ##