PySerials 0.0.0.dev25__py3-none-any.whl → 0.0.0.dev27__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PySerials
3
- Version: 0.0.0.dev25
3
+ Version: 0.0.0.dev27
4
4
  Requires-Python: >=3.10
5
5
  Requires-Dist: jsonschema <5,>=4.21.0
6
6
  Requires-Dist: referencing >=0.35.1
@@ -8,7 +8,7 @@ Requires-Dist: jsonpath-ng <2,>=1.6.1
8
8
  Requires-Dist: ruamel.yaml <0.18,>=0.17.32
9
9
  Requires-Dist: ruamel.yaml.string <1,>=0.1.1
10
10
  Requires-Dist: tomlkit <0.12,>=0.11.8
11
- Requires-Dist: MDit ==0.0.0.dev22
12
- Requires-Dist: ExceptionMan ==0.0.0.dev22
11
+ Requires-Dist: MDit ==0.0.0.dev24
12
+ Requires-Dist: ExceptionMan ==0.0.0.dev24
13
13
  Requires-Dist: ProtocolMan ==0.0.0.dev2
14
14
 
@@ -1,9 +1,9 @@
1
1
  pyserials/__init__.py,sha256=-ySdqDuoUXdi2Pa8uuFa5m1CTAtbZS3SWc5qzaOdR5o,142
2
2
  pyserials/compare.py,sha256=j62A1UIiAm08_xONlbZmU2EcH1GMEpDyEQH66dZ2YMM,1297
3
3
  pyserials/format.py,sha256=dTukpab6WHSyVRQ9SteY5fhr3GFjWFboEl-1cw_udVY,1729
4
- pyserials/nested_dict.py,sha256=8cPs4LykXh4stFpaLINPjrAeSyaOyyTdhg0FZZ2YOYA,3361
4
+ pyserials/nested_dict.py,sha256=VStzCYwuKocdJR4my6xxXVbwR2i060y8XBEJCTglhaw,4021
5
5
  pyserials/read.py,sha256=uucYQH1V4GStwRgRZ2eQIXkH4ukB5qz0EA885grwi68,6592
6
- pyserials/update.py,sha256=GfrFgc1a2qYqR8zs04cngVKcXE0124o20xiJQiSMIxg,9259
6
+ pyserials/update.py,sha256=eCkMRjUZdzrSz0FmCDnHGLgEI1WSC6u6onnADuObIVY,10296
7
7
  pyserials/validate.py,sha256=ti0D_yLzB_HELvf1d5qrarx1Ac-opBMN1Xh5lADRAQU,3664
8
8
  pyserials/write.py,sha256=pN8w78qVsKJjZd_jvPUcZjYp_RJkP7uQzpiXvPOv4lM,1776
9
9
  pyserials/exception/__init__.py,sha256=ZhbggwJUMlTyBhifAivC8ZQxP1Na6lJAwzZs7_YjOSU,151
@@ -11,7 +11,7 @@ pyserials/exception/_base.py,sha256=IdaZwBPBYgiUaWnvN0eMXvQQBqLbN1t766034CK7Hlc,
11
11
  pyserials/exception/read.py,sha256=QyG6ulExXH9u8oDRjUfter70SMDVQqL4nig5s-JzWN4,9252
12
12
  pyserials/exception/update.py,sha256=P0js2-iY2fgO_KLdqedgWE3TTS5Xz15cusZY_wuKIW4,4222
13
13
  pyserials/exception/validate.py,sha256=7UkQEEqCa8HJ20gpTFnLDhT3P5OPLD2oD9fUK2Jcuns,7466
14
- PySerials-0.0.0.dev25.dist-info/METADATA,sha256=AED-NAQT-ry8tShp2z2FomxoGwIx6TG6IQ09Y0lehJ8,438
15
- PySerials-0.0.0.dev25.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
16
- PySerials-0.0.0.dev25.dist-info/top_level.txt,sha256=SAks7WjSjdkv3i9Hvt4gY_P7VQbhhYJN5mf5dqx1aao,10
17
- PySerials-0.0.0.dev25.dist-info/RECORD,,
14
+ PySerials-0.0.0.dev27.dist-info/METADATA,sha256=VQ8uAKR8rawcc3yRKF__GGb1T5WZtHiPSKBKGWSVBRA,438
15
+ PySerials-0.0.0.dev27.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
16
+ PySerials-0.0.0.dev27.dist-info/top_level.txt,sha256=SAks7WjSjdkv3i9Hvt4gY_P7VQbhhYJN5mf5dqx1aao,10
17
+ PySerials-0.0.0.dev27.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.1.0)
2
+ Generator: setuptools (75.2.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
pyserials/nested_dict.py CHANGED
@@ -1,5 +1,12 @@
1
+ from __future__ import annotations as _annotations
2
+
3
+ from typing import TYPE_CHECKING as _TYPE_CHECKING
4
+
1
5
  import pyserials as _ps
2
6
 
7
+ if _TYPE_CHECKING:
8
+ from typing import Callable
9
+
3
10
 
4
11
  class NestedDict:
5
12
 
@@ -8,14 +15,22 @@ class NestedDict:
8
15
  data: dict | None = None,
9
16
  template_marker_start: str = "${{",
10
17
  template_marker_end: str = "}}",
18
+ template_marker_unpack_start: str = "*{{",
19
+ template_marker_unpack_end: str = "}}",
11
20
  template_implicit_root: bool = True,
21
+ template_stringer: Callable[[str], str] = None,
22
+ template_ignore_key_regex: str | None = None,
12
23
  ):
13
24
  self._data = data or {}
14
25
  self._templater = _ps.update.TemplateFiller(
15
26
  marker_start=template_marker_start,
16
27
  marker_end=template_marker_end,
28
+ marker_unpack_start=template_marker_unpack_start,
29
+ marker_unpack_end=template_marker_unpack_end,
17
30
  implicit_root=template_implicit_root,
31
+ stringer=template_stringer,
18
32
  )
33
+ self._ignore_key_regex = template_ignore_key_regex
19
34
  return
20
35
 
21
36
  def fill(
@@ -30,7 +45,9 @@ class NestedDict:
30
45
  value = self.__getitem__(path)
31
46
  if not value:
32
47
  return
33
- filled_value = self.fill_data(data=value, current_path=path, always_list=always_list, recursive=recursive)
48
+ filled_value = self.fill_data(
49
+ data=value, current_path=path, always_list=always_list, recursive=recursive,
50
+ )
34
51
  if not path:
35
52
  self._data = filled_value
36
53
  else:
@@ -50,6 +67,7 @@ class NestedDict:
50
67
  current_path=current_path,
51
68
  always_list=always_list,
52
69
  recursive=recursive,
70
+ ignore_key_regex=self._ignore_key_regex,
53
71
  )
54
72
 
55
73
  def __call__(self):
pyserials/update.py CHANGED
@@ -1,4 +1,5 @@
1
- from typing import Literal as _Literal
1
+ from __future__ import annotations as _annotations
2
+ from typing import TYPE_CHECKING as _TYPE_CHECKING
2
3
  import re as _re
3
4
 
4
5
  import jsonpath_ng as _jsonpath
@@ -6,6 +7,9 @@ from jsonpath_ng import exceptions as _jsonpath_exceptions
6
7
 
7
8
  import pyserials.exception as _exception
8
9
 
10
+ if _TYPE_CHECKING:
11
+ from typing import Literal, Callable
12
+
9
13
 
10
14
  def dict_from_addon(
11
15
  data: dict,
@@ -18,7 +22,7 @@ def dict_from_addon(
18
22
  """Recursively update a dictionary from another dictionary."""
19
23
  def recursive(source: dict, add: dict, path: str, log: dict):
20
24
 
21
- def raise_error(typ: _Literal["duplicate", "type_mismatch"]):
25
+ def raise_error(typ: Literal["duplicate", "type_mismatch"]):
22
26
  raise _exception.update.PySerialsUpdateDictFromAddonError(
23
27
  problem_type=typ,
24
28
  path=fullpath,
@@ -89,20 +93,29 @@ class TemplateFiller:
89
93
  self,
90
94
  marker_start: str = "${{",
91
95
  marker_end: str = "}}",
96
+ marker_unpack_start: str = "*{{",
97
+ marker_unpack_end: str = "}}",
92
98
  implicit_root: bool = True,
99
+ stringer: Callable[[str], str] = str,
93
100
  ):
101
+ def make_regex(start, end):
102
+ start_esc = _re.escape(start)
103
+ end_esc = _re.escape(end)
104
+ regex_sub = rf"{start_esc}([^{end_esc}]+){end_esc}"
105
+ return _re.compile(regex_sub)
106
+
94
107
  self._marker_start = marker_start
95
108
  self._marker_end = marker_end
96
- start = _re.escape(marker_start)
97
- end = _re.escape(marker_end)
98
- regex_sub = rf"{start}([^{end}]+){end}"
99
- self._pattern_template = _re.compile(regex_sub)
109
+ self._pattern_template = make_regex(marker_start, marker_end)
110
+ self._pattern_template_unpack = make_regex(marker_unpack_start, marker_unpack_end)
100
111
  self._add_prefix = implicit_root
112
+ self._stringer = stringer
101
113
  self._data = None
102
114
  self._source = None
103
115
  self._recursive = None
104
116
  self._path = None
105
117
  self._raise_no_match = None
118
+ self._ignore_key_regex = None
106
119
  return
107
120
 
108
121
  def fill(
@@ -113,11 +126,13 @@ class TemplateFiller:
113
126
  always_list: bool = True,
114
127
  recursive: bool = True,
115
128
  raise_no_match: bool = True,
129
+ ignore_key_regex: str | None = None,
116
130
  ):
117
131
  self._data = templated_data
118
132
  self._source = source_data
119
133
  self._recursive = recursive
120
134
  self._raise_no_match = raise_no_match
135
+ self._ignore_key_regex = ignore_key_regex
121
136
  return self._recursive_subst(
122
137
  templ=self._data,
123
138
  current_path=(f"$.{current_path}" if self._add_prefix else current_path) if current_path else "$",
@@ -211,19 +226,27 @@ class TemplateFiller:
211
226
  if match_whole_str:
212
227
  return get_address_value(match_whole_str)
213
228
  return self._pattern_template.sub(
214
- lambda x: str(get_address_value(x)),
229
+ lambda x: self._stringer(get_address_value(x)),
215
230
  templ
216
231
  )
217
232
  if isinstance(templ, list):
218
- return [
219
- self._recursive_subst(
233
+ out = []
234
+ for idx, elem in enumerate(templ):
235
+ elem_filled = self._recursive_subst(
220
236
  elem, f"{current_path}[{idx}]", always_list
221
- ) for idx, elem in enumerate(templ)
222
- ]
237
+ )
238
+ if isinstance(elem, str) and self._pattern_template_unpack.fullmatch(elem):
239
+ out.extend(elem_filled)
240
+ else:
241
+ out.append(elem_filled)
242
+ return out
223
243
  if isinstance(templ, dict):
224
244
  new_dict = {}
225
245
  for key, val in templ.items():
226
246
  key_filled = self._recursive_subst(key, current_path, always_list=False)
247
+ if self._ignore_key_regex and _re.match(self._ignore_key_regex, key_filled):
248
+ new_dict[key_filled] = val
249
+ continue
227
250
  new_dict[key_filled] = self._recursive_subst(
228
251
  val, f"{current_path}.'{key_filled}'", always_list=always_list
229
252
  )