Skip to content

Commit d9eabf0

Browse files
committed
Release version 0.0.0.dev50
1 parent 33f854c commit d9eabf0

4 files changed

Lines changed: 43 additions & 41 deletions

File tree

pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespaces = true
1717
# ----------------------------------------- Project Metadata -------------------------------------
1818
#
1919
[project]
20-
version = "0.0.0.dev49"
20+
version = "0.0.0.dev50"
2121
name = "PySerials"
2222
dependencies = [
2323
"jsonschema >= 4.21.0, < 5",
@@ -26,8 +26,8 @@ dependencies = [
2626
"ruamel.yaml >= 0.17.32, < 0.18", # https://yaml.readthedocs.io/en/stable/
2727
"ruamel.yaml.string >= 0.1.1, < 1",
2828
"tomlkit >= 0.11.8, < 0.12", # https://tomlkit.readthedocs.io/en/stable/,
29-
"MDit == 0.0.0.dev46",
30-
"ExceptionMan == 0.0.0.dev46",
29+
"MDit == 0.0.0.dev47",
30+
"ExceptionMan == 0.0.0.dev47",
3131
"ProtocolMan == 0.0.0.dev2",
3232
]
3333
requires-python = ">=3.10"

requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ jsonpath-ng >= 1.6.1, < 2
44
ruamel.yaml >= 0.17.32, < 0.18
55
ruamel.yaml.string >= 0.1.1, < 1
66
tomlkit >= 0.11.8, < 0.12
7-
MDit == 0.0.0.dev46
8-
ExceptionMan == 0.0.0.dev46
7+
MDit == 0.0.0.dev47
8+
ExceptionMan == 0.0.0.dev47
99
ProtocolMan == 0.0.0.dev2

src/pyserials/exception/update.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,15 +123,15 @@ def __init__(
123123
template_start: str,
124124
template_end: str,
125125
):
126-
self.path_invalid = path_invalid.replace("'", "")
126+
self.path_invalid = path_invalid
127127
self.data_source = data_source
128128
self.template_start = template_start
129129
self.template_end = template_end
130130
parts = description_template.split("{path_invalid}")
131131
if len(parts) > 1:
132-
parts.insert(1, _mdit.element.code_span(self.path_invalid))
132+
parts.insert(1, _mdit.element.code_span(str(self.path_invalid)))
133133
super().__init__(
134-
path=path.replace("'", ""),
134+
path=str(path),
135135
data=data,
136136
data_full=data_full,
137137
problem=_mdit.inline_container(*parts),

src/pyserials/update.py

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ def __init__(
152152

153153
self._pattern_value: dict[int, _RegexPattern] = {}
154154
self._data = None
155-
self._visited_paths = set()
155+
self._visited_paths = {}
156156
return
157157

158158
def fill(
@@ -162,17 +162,17 @@ def fill(
162162
current_path: str = "",
163163
):
164164
self._data = data
165-
self._visited_paths = set()
166-
path = (f"$.{current_path}" if self._add_prefix else current_path) if current_path else "$"
165+
self._visited_paths = {}
166+
path = _jsonpath.parse((f"$.{current_path}" if self._add_prefix else current_path) if current_path else "$")
167167
return self._recursive_subst(
168168
templ=template or data,
169169
current_path=path,
170170
relative_path_anchor=path,
171171
level=0,
172-
current_chain=[path],
172+
current_chain=(path,),
173173
)
174174

175-
def _recursive_subst(self, templ, current_path: str, relative_path_anchor: str, level: int, current_chain: list[str]):
175+
def _recursive_subst(self, templ, current_path: str, relative_path_anchor: str, level: int, current_chain: tuple[str, ...]):
176176

177177
def get_code_value(match: _re.Match | str):
178178

@@ -207,7 +207,7 @@ def getter_function(path: str, default: Any = None, search: bool = False):
207207
path_invalid=current_path,
208208
exception=e,
209209
)
210-
self._visited_paths.add(self._normalize_path(current_path))
210+
self._visited_paths[current_path] = (output, True)
211211
return output
212212

213213
def get_address_value(match: _re.Match | str, return_all_matches: bool = False, from_code: bool = False):
@@ -219,30 +219,30 @@ def get_address_value(match: _re.Match | str, return_all_matches: bool = False,
219219
path_expr = _jsonpath.parse(path)
220220
except _jsonpath_exceptions.JSONPathError:
221221
raise_error(
222-
path_invalid=path,
222+
path_invalid=path_expr,
223223
description_template="JSONPath expression {path_invalid} is invalid.",
224224
)
225225
if num_periods:
226226
if relative_path_anchor != current_path:
227-
path_fields = self._extract_fields(_jsonpath.parse(current_path))
227+
path_fields = self._extract_fields(current_path)
228228
has_template_key = any(field in self._template_keys for field in path_fields)
229229
anchor_path = relative_path_anchor if has_template_key else current_path
230230
else:
231231
anchor_path = current_path
232-
root_path_expr = _jsonpath.parse(anchor_path)
232+
root_path_expr = anchor_path
233233
for period in range(num_periods):
234234
if isinstance(root_path_expr, _jsonpath.Root):
235235
raise_error(
236-
path_invalid=path,
236+
path_invalid=path_expr,
237237
description_template=(
238238
"Relative path {path_invalid} is invalid; "
239239
f"reached root but still {num_periods - period} levels remaining."
240240
),
241241
)
242242
root_path_expr = root_path_expr.left
243243
path_expr = self._concat_json_paths(root_path_expr, path_expr)
244-
value, matched = get_value(path_expr, return_all_matches, from_code)
245-
self._visited_paths.add(self._normalize_path(current_path))
244+
value, matched = self._visited_paths.get(path_expr) or get_value(path_expr, return_all_matches, from_code)
245+
self._visited_paths[path_expr] = (value, matched)
246246
if from_code:
247247
return value, matched
248248
if matched:
@@ -260,7 +260,7 @@ def get_value(jsonpath, return_all_matches: bool, from_code: bool) -> tuple[Any,
260260
return [], True
261261
if self._raise_no_match:
262262
raise_error(
263-
path_invalid=str(jsonpath),
263+
path_invalid=jsonpath,
264264
description_template="JSONPath expression {path_invalid} did not match any data.",
265265
)
266266
return None, False
@@ -274,10 +274,10 @@ def get_value(jsonpath, return_all_matches: bool, from_code: bool) -> tuple[Any,
274274
_rel_path_anchor = relative_path_anchor
275275
return self._recursive_subst(
276276
output,
277-
current_path=str(jsonpath),
277+
current_path=jsonpath,
278278
relative_path_anchor=_rel_path_anchor,
279279
level=0,
280-
current_chain=current_chain + [str(jsonpath)],
280+
current_chain=current_chain + (jsonpath,),
281281
), True
282282

283283
def _rec_match(expr) -> list:
@@ -291,10 +291,10 @@ def _rec_match(expr) -> list:
291291
for left_match in left_matches:
292292
left_match_filled = self._recursive_subst(
293293
templ=left_match.value,
294-
current_path=str(expr.left),
295-
relative_path_anchor=str(expr.left),
294+
current_path=expr.left,
295+
relative_path_anchor=expr.left,
296296
level=0,
297-
current_chain=current_chain + [str(expr.left)],
297+
current_chain=current_chain + (expr.left,),
298298
) if isinstance(left_match.value, str) else left_match.value
299299
right_matches = expr.right.find(left_match_filled)
300300
whole_matches.extend(right_matches)
@@ -341,9 +341,10 @@ def raise_error(path_invalid: str, description_template: str, exception: Excepti
341341
template_end=self._marker_end_value,
342342
) from exception
343343

344+
if current_path in self._visited_paths:
345+
return self._visited_paths[current_path][0]
346+
344347
self._check_endless_loop(templ, current_chain)
345-
# if self._normalize_path(current_path) in self._visited_paths:
346-
# return templ
347348

348349
if isinstance(templ, str):
349350
# Handle value blocks
@@ -391,13 +392,13 @@ def raise_error(path_invalid: str, description_template: str, exception: Excepti
391392
if isinstance(templ, list):
392393
out = []
393394
for idx, elem in enumerate(templ):
394-
new_path = f"{current_path}[{idx}]"
395+
new_path = _jsonpath.Child(current_path, _jsonpath.Index(idx))
395396
elem_filled = self._recursive_subst(
396397
templ=elem,
397398
current_path=new_path,
398399
relative_path_anchor=get_relative_path(new_path),
399400
level=0,
400-
current_chain=current_chain + [new_path],
401+
current_chain=current_chain + (new_path,),
401402
)
402403
if isinstance(elem, str) and self._pattern_unpack.fullmatch(elem):
403404
try:
@@ -409,7 +410,7 @@ def raise_error(path_invalid: str, description_template: str, exception: Excepti
409410
)
410411
else:
411412
out.append(elem_filled)
412-
self._visited_paths.add(self._normalize_path(current_path))
413+
self._visited_paths[current_path] = (out, True)
413414
return out
414415

415416
if isinstance(templ, dict):
@@ -428,29 +429,30 @@ def raise_error(path_invalid: str, description_template: str, exception: Excepti
428429
if key_filled in self._template_keys:
429430
new_dict[key_filled] = val
430431
continue
431-
new_path = f"{current_path}.'{key_filled}'"
432+
new_path = _jsonpath.Child(current_path, _jsonpath.Fields(key_filled))
432433
new_dict[key_filled] = self._recursive_subst(
433434
templ=val,
434435
current_path=new_path,
435436
relative_path_anchor=get_relative_path(new_path),
436437
level=0,
437-
current_chain=current_chain + [new_path],
438+
current_chain=current_chain + (new_path,),
438439
)
439-
self._visited_paths.add(self._normalize_path(current_path))
440+
self._visited_paths[current_path] = (new_dict, True)
440441
return new_dict
441442
return templ
442443

443-
def _check_endless_loop(self,templ, chain: list[str]):
444-
last_idx = len(chain) -1
444+
def _check_endless_loop(self,templ, chain: tuple[str, ...]):
445+
last_idx = len(chain) - 1
445446
first_idx = chain.index(chain[-1])
446447
if first_idx == last_idx:
447448
return
448-
loop = chain[first_idx - 1: -1]
449-
loop_str = "\n".join([f"- {path.replace("'", "")}" for path in loop])
449+
loop = [chain[-2], *chain[first_idx: -2]]
450+
loop_str = "\n".join([f"- {path}" for path in loop])
451+
history_str = "\n".join([f"- {path}" for path in chain])
450452
raise _exception.update.PySerialsUpdateTemplatedDataError(
451-
description_template=f"Path {{path_invalid}} starts a loop:\n{loop_str}",
452-
path_invalid=loop[0],
453-
path=chain[-1],
453+
description_template=f"Path {{path_invalid}} starts a loop:\n{loop_str}\nHistory:\n{history_str}",
454+
path_invalid=chain[-2],
455+
path=chain[0],
454456
data=templ,
455457
data_full=self._data,
456458
data_source=self._data,

0 commit comments

Comments
 (0)