PySerials 0.0.0.dev47__tar.gz → 0.0.0.dev49__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 (24) hide show
  1. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/PKG-INFO +3 -3
  2. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/pyproject.toml +3 -3
  3. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/src/PySerials.egg-info/PKG-INFO +3 -3
  4. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/src/PySerials.egg-info/requires.txt +2 -2
  5. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/src/pyserials/exception/read.py +4 -3
  6. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/src/pyserials/exception/update.py +2 -1
  7. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/src/pyserials/update.py +25 -5
  8. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/src/pyserials/write.py +19 -2
  9. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/README.md +0 -0
  10. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/setup.cfg +0 -0
  11. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/src/PySerials.egg-info/SOURCES.txt +0 -0
  12. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/src/PySerials.egg-info/dependency_links.txt +0 -0
  13. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/src/PySerials.egg-info/not-zip-safe +0 -0
  14. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/src/PySerials.egg-info/top_level.txt +0 -0
  15. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/src/pyserials/__init__.py +0 -0
  16. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/src/pyserials/compare.py +0 -0
  17. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/src/pyserials/exception/__init__.py +0 -0
  18. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/src/pyserials/exception/_base.py +0 -0
  19. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/src/pyserials/exception/validate.py +0 -0
  20. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/src/pyserials/format.py +0 -0
  21. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/src/pyserials/nested_dict.py +0 -0
  22. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/src/pyserials/property_dict.py +0 -0
  23. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/src/pyserials/read.py +0 -0
  24. {pyserials-0.0.0.dev47 → pyserials-0.0.0.dev49}/src/pyserials/validate.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PySerials
3
- Version: 0.0.0.dev47
3
+ Version: 0.0.0.dev49
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.dev44
12
- Requires-Dist: ExceptionMan==0.0.0.dev44
11
+ Requires-Dist: MDit==0.0.0.dev46
12
+ Requires-Dist: ExceptionMan==0.0.0.dev46
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.dev47"
20
+ version = "0.0.0.dev49"
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.dev44",
30
- "ExceptionMan == 0.0.0.dev44",
29
+ "MDit == 0.0.0.dev46",
30
+ "ExceptionMan == 0.0.0.dev46",
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.dev47
3
+ Version: 0.0.0.dev49
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.dev44
12
- Requires-Dist: ExceptionMan==0.0.0.dev44
11
+ Requires-Dist: MDit==0.0.0.dev46
12
+ Requires-Dist: ExceptionMan==0.0.0.dev46
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.dev44
8
- ExceptionMan==0.0.0.dev44
7
+ MDit==0.0.0.dev46
8
+ ExceptionMan==0.0.0.dev46
9
9
  ProtocolMan==0.0.0.dev2
@@ -142,9 +142,10 @@ class PySerialsInvalidDataError(PySerialsReadException):
142
142
  self.problem = cause.problem.strip()
143
143
  if cause.context:
144
144
  self.context = cause.context.strip()
145
- self.context_line = cause.context_mark.line + 1
146
- self.context_column = cause.context_mark.column + 1
147
- self.context_data_type = cause.context_mark.name.removeprefix("<").removesuffix(">")
145
+ if cause.context_mark:
146
+ self.context_line = cause.context_mark.line + 1
147
+ self.context_column = cause.context_mark.column + 1
148
+ self.context_data_type = cause.context_mark.name.removeprefix("<").removesuffix(">")
148
149
  elif isinstance(cause, _json.JSONDecodeError):
149
150
  self.problem = cause.msg
150
151
  self.problem_line = cause.lineno
@@ -128,7 +128,8 @@ class PySerialsUpdateTemplatedDataError(PySerialsUpdateException):
128
128
  self.template_start = template_start
129
129
  self.template_end = template_end
130
130
  parts = description_template.split("{path_invalid}")
131
- parts.insert(1, _mdit.element.code_span(self.path_invalid))
131
+ if len(parts) > 1:
132
+ parts.insert(1, _mdit.element.code_span(self.path_invalid))
132
133
  super().__init__(
133
134
  path=path.replace("'", ""),
134
135
  data=data,
@@ -152,6 +152,7 @@ class TemplateFiller:
152
152
 
153
153
  self._pattern_value: dict[int, _RegexPattern] = {}
154
154
  self._data = None
155
+ self._visited_paths = set()
155
156
  return
156
157
 
157
158
  def fill(
@@ -161,6 +162,7 @@ class TemplateFiller:
161
162
  current_path: str = "",
162
163
  ):
163
164
  self._data = data
165
+ self._visited_paths = set()
164
166
  path = (f"$.{current_path}" if self._add_prefix else current_path) if current_path else "$"
165
167
  return self._recursive_subst(
166
168
  templ=template or data,
@@ -198,12 +200,15 @@ class TemplateFiller:
198
200
  local_context = {}
199
201
  try:
200
202
  exec(code_str_full, global_context, local_context)
201
- return local_context["__inline_code__"]()
203
+ output = local_context["__inline_code__"]()
202
204
  except Exception as e:
203
205
  raise_error(
204
206
  description_template=f"Code at {{path_invalid}} raised an exception: {e}\n{code_str_full}",
205
207
  path_invalid=current_path,
208
+ exception=e,
206
209
  )
210
+ self._visited_paths.add(self._normalize_path(current_path))
211
+ return output
207
212
 
208
213
  def get_address_value(match: _re.Match | str, return_all_matches: bool = False, from_code: bool = False):
209
214
  raw_path = match if isinstance(match, str) else str(match.group(1))
@@ -237,6 +242,7 @@ class TemplateFiller:
237
242
  root_path_expr = root_path_expr.left
238
243
  path_expr = self._concat_json_paths(root_path_expr, path_expr)
239
244
  value, matched = get_value(path_expr, return_all_matches, from_code)
245
+ self._visited_paths.add(self._normalize_path(current_path))
240
246
  if from_code:
241
247
  return value, matched
242
248
  if matched:
@@ -323,7 +329,7 @@ class TemplateFiller:
323
329
  values = get_address_value(path)
324
330
  return self._unpack_string_joiner.join([self._stringer(val) for val in values])
325
331
 
326
- def raise_error(path_invalid: str, description_template: str):
332
+ def raise_error(path_invalid: str, description_template: str, exception: Exception | None = None):
327
333
  raise _exception.update.PySerialsUpdateTemplatedDataError(
328
334
  description_template=description_template,
329
335
  path_invalid=path_invalid,
@@ -333,9 +339,11 @@ class TemplateFiller:
333
339
  data_source=self._data,
334
340
  template_start=self._marker_start_value,
335
341
  template_end=self._marker_end_value,
336
- )
342
+ ) from exception
337
343
 
338
344
  self._check_endless_loop(templ, current_chain)
345
+ # if self._normalize_path(current_path) in self._visited_paths:
346
+ # return templ
339
347
 
340
348
  if isinstance(templ, str):
341
349
  # Handle value blocks
@@ -361,7 +369,7 @@ class TemplateFiller:
361
369
  unpack_value = fill_nested_values(unpack_value)
362
370
  submatch_list = self._pattern_list.fullmatch(unpack_value)
363
371
  if submatch_list:
364
- return get_address_value(unpack_value, return_all_matches=True)
372
+ return get_address_value(submatch_list, return_all_matches=True)
365
373
  return get_address_value(unpack_value)
366
374
  # Handle strings
367
375
  code_blocks_filled = self._pattern_code.sub(
@@ -392,9 +400,16 @@ class TemplateFiller:
392
400
  current_chain=current_chain + [new_path],
393
401
  )
394
402
  if isinstance(elem, str) and self._pattern_unpack.fullmatch(elem):
395
- out.extend(elem_filled)
403
+ try:
404
+ out.extend(elem_filled)
405
+ except TypeError as e:
406
+ raise_error(
407
+ path_invalid=current_path,
408
+ description_template=str(e)
409
+ )
396
410
  else:
397
411
  out.append(elem_filled)
412
+ self._visited_paths.add(self._normalize_path(current_path))
398
413
  return out
399
414
 
400
415
  if isinstance(templ, dict):
@@ -421,6 +436,7 @@ class TemplateFiller:
421
436
  level=0,
422
437
  current_chain=current_chain + [new_path],
423
438
  )
439
+ self._visited_paths.add(self._normalize_path(current_path))
424
440
  return new_dict
425
441
  return templ
426
442
 
@@ -479,6 +495,10 @@ class TemplateFiller:
479
495
  _recursive_extract(jsonpath)
480
496
  return fields
481
497
 
498
+ @staticmethod
499
+ def _normalize_path(path: str) -> str:
500
+ return path.replace("'", "")
501
+
482
502
  def _concat_json_paths(self, path1, path2):
483
503
  if not isinstance(path2, _jsonpath.Child):
484
504
  return _jsonpath.Child(path1, path2)
@@ -2,6 +2,7 @@ from typing import Literal as _Literal
2
2
  from pathlib import Path as _Path
3
3
  import json as _json
4
4
  import ruamel.yaml as _yaml
5
+ from ruamel.yaml import scalarstring as _yaml_scalar_string
5
6
  import tomlkit as _tomlkit
6
7
 
7
8
 
@@ -22,8 +23,16 @@ def to_string(
22
23
  def to_yaml_string(
23
24
  data: dict | list | str | int | float | bool | _yaml.CommentedMap | _yaml.CommentedSeq,
24
25
  end_of_file_newline: bool = True,
26
+ indent_mapping: int = 2,
27
+ indent_sequence: int = 4,
28
+ indent_sequence_offset: int = 2,
29
+ multiline_string_to_block: bool = True,
25
30
  ) -> str:
26
- yaml_syntax = _yaml.YAML(typ=["rt", "string"]).dumps(data, add_final_eol=False).removesuffix("\n...")
31
+ yaml = _yaml.YAML(typ=["rt", "string"])
32
+ yaml.indent(mapping=indent_mapping, sequence=indent_sequence, offset=indent_sequence_offset)
33
+ if multiline_string_to_block:
34
+ _yaml_scalar_string.walk_tree(data)
35
+ yaml_syntax = yaml.dumps(data, add_final_eol=False).removesuffix("\n...")
27
36
  return f"{yaml_syntax}\n" if end_of_file_newline else yaml_syntax
28
37
 
29
38
 
@@ -46,9 +55,17 @@ def to_yaml_file(
46
55
  data: dict | list | str | int | float | bool | _yaml.CommentedMap | _yaml.CommentedSeq,
47
56
  path: str | _Path,
48
57
  make_dirs: bool = True,
58
+ indent_mapping: int = 2,
59
+ indent_sequence: int = 4,
60
+ indent_sequence_offset: int = 2,
61
+ multiline_string_to_block: bool = True,
49
62
  ):
50
63
  path = _Path(path).resolve()
51
64
  if make_dirs:
52
65
  path.parent.mkdir(parents=True, exist_ok=True)
53
- _yaml.YAML().dump(data, path)
66
+ yaml = _yaml.YAML()
67
+ yaml.indent(mapping=indent_mapping, sequence=indent_sequence, offset=indent_sequence_offset)
68
+ if multiline_string_to_block:
69
+ _yaml_scalar_string.walk_tree(data)
70
+ yaml.dump(data, path)
54
71
  return