PySerials 0.0.0.dev31__tar.gz → 0.0.0.dev32__tar.gz

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.
Files changed (23) hide show
  1. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/PKG-INFO +3 -3
  2. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/pyproject.toml +3 -3
  3. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/src/PySerials.egg-info/PKG-INFO +3 -3
  4. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/src/PySerials.egg-info/requires.txt +2 -2
  5. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/src/pyserials/nested_dict.py +6 -0
  6. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/src/pyserials/update.py +41 -4
  7. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/README.md +0 -0
  8. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/setup.cfg +0 -0
  9. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/src/PySerials.egg-info/SOURCES.txt +0 -0
  10. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/src/PySerials.egg-info/dependency_links.txt +0 -0
  11. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/src/PySerials.egg-info/not-zip-safe +0 -0
  12. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/src/PySerials.egg-info/top_level.txt +0 -0
  13. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/src/pyserials/__init__.py +0 -0
  14. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/src/pyserials/compare.py +0 -0
  15. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/src/pyserials/exception/__init__.py +0 -0
  16. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/src/pyserials/exception/_base.py +0 -0
  17. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/src/pyserials/exception/read.py +0 -0
  18. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/src/pyserials/exception/update.py +0 -0
  19. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/src/pyserials/exception/validate.py +0 -0
  20. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/src/pyserials/format.py +0 -0
  21. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/src/pyserials/read.py +0 -0
  22. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/src/pyserials/validate.py +0 -0
  23. {pyserials-0.0.0.dev31 → pyserials-0.0.0.dev32}/src/pyserials/write.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PySerials
3
- Version: 0.0.0.dev31
3
+ Version: 0.0.0.dev32
4
4
  Requires-Python: >=3.10
5
5
  Requires-Dist: jsonschema<5,>=4.21.0
6
6
  Requires-Dist: referencing>=0.35.1
@@ -8,6 +8,6 @@ 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.dev28
12
- Requires-Dist: ExceptionMan==0.0.0.dev28
11
+ Requires-Dist: MDit==0.0.0.dev29
12
+ Requires-Dist: ExceptionMan==0.0.0.dev29
13
13
  Requires-Dist: ProtocolMan==0.0.0.dev2
@@ -17,7 +17,7 @@ namespaces = true
17
17
  # ----------------------------------------- Project Metadata -------------------------------------
18
18
  #
19
19
  [project]
20
- version = "0.0.0.dev31"
20
+ version = "0.0.0.dev32"
21
21
  name = "PySerials"
22
22
  dependencies = [
23
23
  "jsonschema >= 4.21.0, < 5",
@@ -26,8 +26,8 @@ dependencies = [
26
26
  "ruamel.yaml >= 0.17.32, < 0.18", # https://yaml.readthedocs.io/en/stable/
27
27
  "ruamel.yaml.string >= 0.1.1, < 1",
28
28
  "tomlkit >= 0.11.8, < 0.12", # https://tomlkit.readthedocs.io/en/stable/,
29
- "MDit == 0.0.0.dev28",
30
- "ExceptionMan == 0.0.0.dev28",
29
+ "MDit == 0.0.0.dev29",
30
+ "ExceptionMan == 0.0.0.dev29",
31
31
  "ProtocolMan == 0.0.0.dev2",
32
32
  ]
33
33
  requires-python = ">=3.10"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PySerials
3
- Version: 0.0.0.dev31
3
+ Version: 0.0.0.dev32
4
4
  Requires-Python: >=3.10
5
5
  Requires-Dist: jsonschema<5,>=4.21.0
6
6
  Requires-Dist: referencing>=0.35.1
@@ -8,6 +8,6 @@ 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.dev28
12
- Requires-Dist: ExceptionMan==0.0.0.dev28
11
+ Requires-Dist: MDit==0.0.0.dev29
12
+ Requires-Dist: ExceptionMan==0.0.0.dev29
13
13
  Requires-Dist: ProtocolMan==0.0.0.dev2
@@ -4,6 +4,6 @@ jsonpath-ng<2,>=1.6.1
4
4
  ruamel.yaml<0.18,>=0.17.32
5
5
  ruamel.yaml.string<1,>=0.1.1
6
6
  tomlkit<0.12,>=0.11.8
7
- MDit==0.0.0.dev28
8
- ExceptionMan==0.0.0.dev28
7
+ MDit==0.0.0.dev29
8
+ ExceptionMan==0.0.0.dev29
9
9
  ProtocolMan==0.0.0.dev2
@@ -28,6 +28,7 @@ class NestedDict:
28
28
  raise_no_match: bool = True,
29
29
  leave_no_match: bool = False,
30
30
  no_match_value: Any = None,
31
+ code_context: dict[str, Any] | None = None,
31
32
  stringer: Callable[[str], str] = str,
32
33
  unpack_string_joiner: str = ", ",
33
34
  relative_template_keys: list[str] | None = None,
@@ -51,6 +52,7 @@ class NestedDict:
51
52
  self._raise_no_match = raise_no_match
52
53
  self._leave_no_match = leave_no_match
53
54
  self._no_match_value = no_match_value
55
+ self._code_context = code_context or {}
54
56
  self._stringer = stringer
55
57
  self._unpack_string_joiner = unpack_string_joiner
56
58
  self._relative_template_keys = relative_template_keys or []
@@ -63,6 +65,7 @@ class NestedDict:
63
65
  recursive: bool | None = None,
64
66
  raise_no_match: bool | None = None,
65
67
  leave_no_match: bool | None = None,
68
+ code_context: dict[str, Any] | None = None,
66
69
  stringer: Callable[[str], str] | None = None,
67
70
  unpack_string_joiner: str | None = None,
68
71
  level: int = 0,
@@ -79,6 +82,7 @@ class NestedDict:
79
82
  recursive=recursive,
80
83
  raise_no_match=raise_no_match,
81
84
  leave_no_match=leave_no_match,
85
+ code_context=code_context,
82
86
  stringer=stringer,
83
87
  unpack_string_joiner=unpack_string_joiner,
84
88
  level=level,
@@ -97,6 +101,7 @@ class NestedDict:
97
101
  raise_no_match: bool | None = None,
98
102
  leave_no_match: bool | None = None,
99
103
  stringer: Callable[[str], str] | None = None,
104
+ code_context: dict[str, Any] | None = None,
100
105
  unpack_string_joiner: str | None = None,
101
106
  level: int = 0,
102
107
  ):
@@ -108,6 +113,7 @@ class NestedDict:
108
113
  raise_no_match=raise_no_match if raise_no_match is not None else self._raise_no_match,
109
114
  leave_no_match=leave_no_match if leave_no_match is not None else self._leave_no_match,
110
115
  no_match_value=self._no_match_value,
116
+ code_context=code_context if code_context is not None else self._code_context,
111
117
  stringer=stringer if stringer is not None else self._stringer,
112
118
  unpack_string_joiner=unpack_string_joiner if unpack_string_joiner is not None else self._unpack_string_joiner,
113
119
  relative_template_keys=self._relative_template_keys,
@@ -137,8 +137,10 @@ class TemplateFiller:
137
137
  self._ignore_templates = True
138
138
  self._leave_no_match = False
139
139
  self._no_match_value = None
140
+ self._code_context = {}
140
141
  self._stringer = str
141
142
  self._unpack_string_joiner = ", "
143
+ self._path_history = []
142
144
  return
143
145
 
144
146
  def _get_value_regex_pattern(self, level: int = 0) -> _RegexPattern:
@@ -162,6 +164,7 @@ class TemplateFiller:
162
164
  raise_no_match: bool = True,
163
165
  leave_no_match: bool = False,
164
166
  no_match_value: Any = None,
167
+ code_context: dict[str, Any] | None = None,
165
168
  stringer: Callable[[str], str] = str,
166
169
  unpack_string_joiner: str = ", ",
167
170
  relative_template_keys: list[str] | None = None,
@@ -174,10 +177,12 @@ class TemplateFiller:
174
177
  self._raise_no_match = raise_no_match
175
178
  self._leave_no_match = leave_no_match
176
179
  self._no_match_value = no_match_value
180
+ self._code_context = code_context or {}
177
181
  self._stringer = stringer
178
182
  self._unpack_string_joiner = unpack_string_joiner
179
183
  self._add_prefix = implicit_root
180
184
  self._template_keys = relative_template_keys or []
185
+ self._path_history = []
181
186
  path = (f"$.{current_path}" if self._add_prefix else current_path) if current_path else "$"
182
187
  if not relative_template_keys:
183
188
  self._ignore_templates = False
@@ -198,6 +203,7 @@ class TemplateFiller:
198
203
  self._source = first_pass
199
204
  self._data = first_pass
200
205
  self._ignore_templates = False
206
+ self._path_history = []
201
207
  return self._recursive_subst(
202
208
  templ=self._data,
203
209
  current_path=path,
@@ -205,13 +211,13 @@ class TemplateFiller:
205
211
  level=level,
206
212
  )
207
213
 
208
- def _recursive_subst(self, templ, current_path: str, relative_path_anchor: str, level: int):
214
+ def _recursive_subst(self, templ, current_path: str, relative_path_anchor: str, level: int, internal=False):
209
215
 
210
216
  def get_code_value(code_str: str):
211
217
  code_lines = ["def __inline_code__():"]
212
218
  code_lines.extend([f" {line}" for line in code_str.strip("\n").splitlines()])
213
219
  code_str_full = "\n".join(code_lines)
214
- global_context = {}
220
+ global_context = self._code_context.copy()
215
221
  local_context = {}
216
222
  try:
217
223
  exec(code_str_full, global_context, local_context)
@@ -250,7 +256,7 @@ class TemplateFiller:
250
256
  ),
251
257
  )
252
258
  root_path_expr = root_path_expr.left
253
- path_expr = root_path_expr.child(path_expr)
259
+ path_expr = _jsonpath.Child(root_path_expr, path_expr)
254
260
  value, matched = get_value(path_expr, return_all_matches)
255
261
  if matched:
256
262
  return value
@@ -261,7 +267,9 @@ class TemplateFiller:
261
267
  def get_value(jsonpath, return_all_matches: bool) -> tuple[Any, bool]:
262
268
  matches = _rec_match(jsonpath)
263
269
  if not matches:
264
- if not return_all_matches and self._raise_no_match:
270
+ if return_all_matches:
271
+ return [], True
272
+ if self._raise_no_match:
265
273
  raise_error(
266
274
  path_invalid=str(jsonpath),
267
275
  description_template="JSONPath expression {path_invalid} did not match any data.",
@@ -333,6 +341,22 @@ class TemplateFiller:
333
341
  values = get_address_value(match)
334
342
  return self._unpack_string_joiner.join([self._stringer(val) for val in values])
335
343
 
344
+ # if not internal:
345
+ # self._path_history.append(current_path)
346
+ # loop = self._find_loop()
347
+ # if loop:
348
+ # loop_str = "\n".join([f"- {path.replace("'", "")}" for path in loop])
349
+ # raise _exception.update.PySerialsUpdateTemplatedDataError(
350
+ # description_template=f"Path {{path_invalid}} starts a loop: {loop_str}",
351
+ # path_invalid=loop[0],
352
+ # path=current_path,
353
+ # data=templ,
354
+ # data_full=self._data,
355
+ # data_source=self._source,
356
+ # template_start=self._marker_start_value,
357
+ # template_end=self._marker_end_value,
358
+ # )
359
+
336
360
  if isinstance(templ, str):
337
361
  pattern_nested = self._get_value_regex_pattern(level=level + 1)
338
362
  templ_nested_filled = pattern_nested.sub(
@@ -341,6 +365,7 @@ class TemplateFiller:
341
365
  current_path=current_path,
342
366
  relative_path_anchor=get_relative_path(current_path),
343
367
  level=level+1,
368
+ internal=True,
344
369
  ),
345
370
  templ
346
371
  )
@@ -401,6 +426,7 @@ class TemplateFiller:
401
426
  current_path=current_path,
402
427
  relative_path_anchor=relative_path_anchor,
403
428
  level=0,
429
+ internal=True,
404
430
  )
405
431
  if isinstance(key, str) and self._pattern_unpack.fullmatch(key.strip()):
406
432
  new_dict.update(key_filled)
@@ -418,6 +444,17 @@ class TemplateFiller:
418
444
  return new_dict
419
445
  return templ
420
446
 
447
+ def _find_loop(self):
448
+ for pattern_length in range(1, len(self._path_history) // 2 + 1):
449
+ # Slice the end of the list into two consecutive patterns
450
+ pattern = self._path_history[-pattern_length:]
451
+ previous_pattern = self._path_history[-2 * pattern_length:-pattern_length]
452
+ # Check if the two patterns are the same
453
+ if pattern == previous_pattern:
454
+ pattern.insert(0, pattern[-1])
455
+ return pattern
456
+ return
457
+
421
458
  @staticmethod
422
459
  def _remove_leading_periods(s: str) -> (str, int):
423
460
  match = _re.match(r"^(\.*)(.*)", s)