j-perm 0.2.1.1__py3-none-any.whl → 0.2.2__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.
j_perm/constructs/ref.py CHANGED
@@ -4,7 +4,6 @@ import copy
4
4
  from typing import Mapping, Any
5
5
 
6
6
  from ..special_resolver import _MISSING, SpecialRegistry
7
- from ..utils.pointers import maybe_slice
8
7
 
9
8
 
10
9
  @SpecialRegistry.register("$ref")
@@ -14,7 +13,7 @@ def of_ref(node: Mapping[str, Any], src: Mapping[str, Any], engine: "ActionEngin
14
13
 
15
14
  dflt = node.get("$default", _MISSING)
16
15
  try:
17
- return copy.deepcopy(maybe_slice(ptr, src))
16
+ return copy.deepcopy(engine.pointer_manager.maybe_slice(ptr, src))
18
17
  except Exception:
19
18
  if dflt is not _MISSING:
20
19
  return copy.deepcopy(dflt)
j_perm/engine.py CHANGED
@@ -6,6 +6,7 @@ from typing import Any, List, Mapping, TypeAlias, MutableMapping, Union
6
6
 
7
7
  from .normalizer import Normalizer
8
8
  from .op_handler import Handlers
9
+ from .pointers import PointerManager
9
10
  from .special_resolver import SpecialResolver
10
11
  from .subst import TemplateSubstitutor
11
12
 
@@ -48,6 +49,7 @@ class ActionEngine:
48
49
  special: SpecialResolver = field(default_factory=SpecialResolver)
49
50
  substitutor: TemplateSubstitutor = field(default_factory=TemplateSubstitutor)
50
51
  normalizer: Normalizer = field(default_factory=Normalizer)
52
+ pointer_manager: PointerManager = field(default_factory=PointerManager)
51
53
 
52
54
  def apply_actions(
53
55
  self,
j_perm/normalizer.py CHANGED
@@ -19,6 +19,7 @@ class ShorthandRegistry:
19
19
  cls._rules[name] = fn
20
20
  cls._default_priority[name] = priority
21
21
  return fn
22
+
22
23
  return deco
23
24
 
24
25
  @classmethod
j_perm/ops/_assert.py CHANGED
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  from typing import MutableMapping, Any, Mapping
4
4
 
5
5
  from ..op_handler import OpRegistry
6
- from ..utils.pointers import jptr_get
7
6
 
8
7
 
9
8
  @OpRegistry.register("assert")
@@ -17,7 +16,7 @@ def op_assert(
17
16
  path = engine.substitutor.substitute(step["path"], src)
18
17
 
19
18
  try:
20
- current = jptr_get(src, path)
19
+ current = engine.pointer_manager.get_pointer(src, path)
21
20
  except Exception:
22
21
  raise AssertionError(f"'{path}' does not exist in source")
23
22
 
j_perm/ops/_assert_d.py CHANGED
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  from typing import MutableMapping, Any, Mapping
4
4
 
5
5
  from ..op_handler import OpRegistry
6
- from ..utils.pointers import jptr_get
7
6
 
8
7
 
9
8
  @OpRegistry.register("assertD")
@@ -17,7 +16,7 @@ def op_assert_d(
17
16
  path = engine.substitutor.substitute(step["path"], dest)
18
17
 
19
18
  try:
20
- current = jptr_get(dest, path)
19
+ current = engine.pointer_manager.get_pointer(dest, path)
21
20
  except Exception:
22
21
  raise AssertionError(f"'{path}' does not exist in destination")
23
22
 
j_perm/ops/_exec.py CHANGED
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  from typing import MutableMapping, Any, Mapping
4
4
 
5
5
  from ..op_handler import OpRegistry
6
- from ..utils.pointers import maybe_slice
7
6
 
8
7
 
9
8
  @OpRegistry.register("exec")
@@ -26,7 +25,7 @@ def op_exec(
26
25
  if has_from:
27
26
  actions_ptr = engine.substitutor.substitute(step["from"], src)
28
27
  try:
29
- actions = maybe_slice(actions_ptr, src)
28
+ actions = engine.pointer_manager.maybe_slice(actions_ptr, src)
30
29
  except Exception:
31
30
  if "default" in step:
32
31
  actions = engine.special.resolve(step["default"], src, engine)
j_perm/ops/_if.py CHANGED
@@ -4,7 +4,6 @@ import copy
4
4
  from typing import MutableMapping, Any, Mapping
5
5
 
6
6
  from ..op_handler import OpRegistry
7
- from ..utils.pointers import maybe_slice
8
7
 
9
8
 
10
9
  @OpRegistry.register("if")
@@ -18,7 +17,7 @@ def op_if(
18
17
  if "path" in step:
19
18
  try:
20
19
  ptr = engine.substitutor.substitute(step["path"], src)
21
- current = maybe_slice(ptr, dest)
20
+ current = engine.pointer_manager.maybe_slice(ptr, dest)
22
21
  missing = False
23
22
  except Exception:
24
23
  current = None
j_perm/ops/copy.py CHANGED
@@ -5,7 +5,6 @@ from typing import MutableMapping, Any, Mapping
5
5
 
6
6
  from .set import op_set
7
7
  from ..op_handler import OpRegistry
8
- from ..utils.pointers import maybe_slice
9
8
 
10
9
 
11
10
  @OpRegistry.register("copy")
@@ -24,7 +23,7 @@ def op_copy(
24
23
  ignore = bool(step.get("ignore_missing", False))
25
24
 
26
25
  try:
27
- value = copy.deepcopy(maybe_slice(ptr, src))
26
+ value = copy.deepcopy(engine.pointer_manager.maybe_slice(ptr, src))
28
27
  except Exception:
29
28
  if "default" in step:
30
29
  value = copy.deepcopy(step["default"])
j_perm/ops/copy_d.py CHANGED
@@ -5,7 +5,6 @@ from typing import MutableMapping, Any, Mapping
5
5
 
6
6
  from .set import op_set
7
7
  from ..op_handler import OpRegistry
8
- from ..utils.pointers import maybe_slice
9
8
 
10
9
 
11
10
  @OpRegistry.register("copyD")
@@ -23,7 +22,7 @@ def op_copy_d(
23
22
  ignore = bool(step.get("ignore_missing", False))
24
23
 
25
24
  try:
26
- value = copy.deepcopy(maybe_slice(ptr, dest))
25
+ value = copy.deepcopy(engine.pointer_manager.maybe_slice(ptr, dest))
27
26
  except Exception:
28
27
  if "default" in step:
29
28
  value = copy.deepcopy(step["default"])
j_perm/ops/delete.py CHANGED
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  from typing import MutableMapping, Any, Mapping
4
4
 
5
5
  from ..op_handler import OpRegistry
6
- from ..utils.pointers import jptr_ensure_parent
7
6
 
8
7
 
9
8
  @OpRegistry.register("delete")
@@ -18,7 +17,7 @@ def op_delete(
18
17
  ignore = bool(step.get("ignore_missing", True))
19
18
 
20
19
  try:
21
- parent, leaf = jptr_ensure_parent(dest, path, create=False)
20
+ parent, leaf = engine.pointer_manager.ensure_parent(dest, path, create=False)
22
21
 
23
22
  if leaf == "-":
24
23
  raise ValueError("'-' not allowed in delete")
j_perm/ops/distinct.py CHANGED
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  from typing import MutableMapping, Any, Mapping
4
4
 
5
5
  from ..op_handler import OpRegistry
6
- from ..utils.pointers import jptr_get
7
6
 
8
7
 
9
8
  @OpRegistry.register("distinct")
@@ -15,7 +14,7 @@ def op_distinct(
15
14
  ) -> MutableMapping[str, Any]:
16
15
  """Remove duplicates from a list at the given path, preserving order."""
17
16
  path = engine.substitutor.substitute(step["path"], src)
18
- lst = jptr_get(dest, path)
17
+ lst = engine.pointer_manager.get_pointer(dest, path)
19
18
 
20
19
  if not isinstance(lst, list):
21
20
  raise TypeError(f"{path} is not a list (distinct)")
@@ -27,7 +26,7 @@ def op_distinct(
27
26
  unique = []
28
27
  for item in lst:
29
28
  if key is not None:
30
- filter_item = jptr_get(item, key_path)
29
+ filter_item = engine.pointer_manager.get_pointer(item, key_path)
31
30
  else:
32
31
  filter_item = item
33
32
 
j_perm/ops/foreach.py CHANGED
@@ -4,7 +4,6 @@ import copy
4
4
  from typing import MutableMapping, Any, Mapping
5
5
 
6
6
  from ..op_handler import OpRegistry
7
- from ..utils.pointers import maybe_slice
8
7
 
9
8
 
10
9
  @OpRegistry.register("foreach")
@@ -21,7 +20,7 @@ def op_foreach(
21
20
  skip_empty = bool(step.get("skip_empty", True))
22
21
 
23
22
  try:
24
- arr = maybe_slice(arr_ptr, src)
23
+ arr = engine.pointer_manager.maybe_slice(arr_ptr, src)
25
24
  except Exception:
26
25
  arr = default
27
26
 
j_perm/ops/set.py CHANGED
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  from typing import Any, Mapping, MutableMapping
4
4
 
5
5
  from ..op_handler import OpRegistry
6
- from ..utils.pointers import jptr_ensure_parent
7
6
 
8
7
 
9
8
  @OpRegistry.register("set")
@@ -22,12 +21,12 @@ def op_set(
22
21
  if isinstance(value, (str, list, Mapping)):
23
22
  value = engine.substitutor.substitute(value, src)
24
23
 
25
- parent, leaf = jptr_ensure_parent(dest, path, create=create)
24
+ parent, leaf = engine.pointer_manager.ensure_parent(dest, path, create=create)
26
25
 
27
26
  if leaf == "-":
28
27
  if not isinstance(parent, list):
29
28
  if create:
30
- grand, last = jptr_ensure_parent(dest, path.rsplit("/", 1)[0], create=True)
29
+ grand, last = engine.pointer_manager.ensure_parent(dest, path.rsplit("/", 1)[0], create=True)
31
30
  if not isinstance(grand[last], list):
32
31
  if grand[last] == {}:
33
32
  grand[last] = []
j_perm/ops/update.py CHANGED
@@ -4,7 +4,6 @@ import copy
4
4
  from typing import MutableMapping, Any, Mapping
5
5
 
6
6
  from ..op_handler import OpRegistry
7
- from ..utils.pointers import maybe_slice, jptr_ensure_parent
8
7
 
9
8
 
10
9
  @OpRegistry.register("update")
@@ -22,7 +21,7 @@ def op_update(
22
21
  if "from" in step:
23
22
  ptr = engine.substitutor.substitute(step["from"], src)
24
23
  try:
25
- update_value = copy.deepcopy(maybe_slice(ptr, src))
24
+ update_value = copy.deepcopy(engine.pointer_manager.maybe_slice(ptr, src))
26
25
  except Exception:
27
26
  if "default" in step:
28
27
  update_value = copy.deepcopy(step["default"])
j_perm/pointers.py ADDED
@@ -0,0 +1,107 @@
1
+ from __future__ import annotations
2
+
3
+ import re
4
+ from typing import Any, Mapping, MutableMapping, List, Tuple
5
+
6
+
7
+ class PointerManager:
8
+ _SLICE_RE = re.compile(r"(.+)\[(-?\d*):(-?\d*)]$")
9
+
10
+ def _decode(self, tok: str) -> str:
11
+ """Decode a single JSON Pointer token, handling RFC6901-style escapes."""
12
+ return (
13
+ tok.replace("~0", "~")
14
+ .replace("~1", "/")
15
+ .replace("~2", "$")
16
+ .replace("~3", ".")
17
+ )
18
+
19
+ def get_pointer(self, doc: Any, ptr: str) -> Any:
20
+ """Read value by JSON Pointer, supporting root and '..' segments."""
21
+ if ptr in ("", "/", "."):
22
+ return doc
23
+
24
+ tokens = ptr.lstrip("/").split("/")
25
+ cur: Any = doc
26
+ parents: List[Tuple[Any, Any]] = []
27
+
28
+ for raw_tok in tokens:
29
+ if raw_tok == "..":
30
+ if parents:
31
+ cur, _ = parents.pop()
32
+ else:
33
+ cur = doc
34
+ continue
35
+
36
+ key = self._decode(raw_tok)
37
+
38
+ if isinstance(cur, (list, tuple)):
39
+ idx = int(key)
40
+ parents.append((cur, idx))
41
+ cur = cur[idx]
42
+ else:
43
+ parents.append((cur, key))
44
+ cur = cur[key]
45
+
46
+ return cur
47
+
48
+ def maybe_slice(self, ptr: str, src: Mapping[str, Any]) -> Any:
49
+ """Resolve a pointer and optional Python-style slice suffix '[start:end]' for arrays."""
50
+ m = self._SLICE_RE.match(ptr)
51
+ if m:
52
+ base, s, e = m.groups()
53
+ seq = self.get_pointer(src, base)
54
+ if not isinstance(seq, (list, tuple)):
55
+ raise TypeError(f"{base} is not a list (slice requested)")
56
+
57
+ start = int(s) if s else None
58
+ end = int(e) if e else None
59
+ return seq[start:end]
60
+
61
+ return self.get_pointer(src, ptr)
62
+
63
+ def ensure_parent(
64
+ self,
65
+ doc: MutableMapping[str, Any],
66
+ ptr: str,
67
+ *,
68
+ create: bool = False,
69
+ ):
70
+ """Return (container, leaf_key) for ptr, optionally creating intermediate nodes."""
71
+ raw_parts = ptr.lstrip("/").split("/")
72
+ parts: List[str] = []
73
+
74
+ for raw in raw_parts:
75
+ if raw == "..":
76
+ if parts:
77
+ parts.pop()
78
+ continue
79
+ parts.append(raw)
80
+
81
+ if not parts:
82
+ return doc, ""
83
+
84
+ cur: Any = doc
85
+
86
+ for raw in parts[:-1]:
87
+ token = self._decode(raw)
88
+
89
+ if isinstance(cur, list):
90
+ idx = int(token)
91
+ if idx >= len(cur):
92
+ if create:
93
+ while idx >= len(cur):
94
+ cur.append({})
95
+ else:
96
+ raise IndexError(f"{ptr}: index {idx} out of range")
97
+ cur = cur[idx]
98
+ else:
99
+ if token not in cur:
100
+ if create:
101
+ cur[token] = {}
102
+ else:
103
+ raise KeyError(f"{ptr}: missing key '{token}'")
104
+ cur = cur[token]
105
+
106
+ leaf = self._decode(parts[-1])
107
+ return cur, leaf
j_perm/subst.py CHANGED
@@ -8,8 +8,6 @@ from typing import Any, Callable, Mapping
8
8
  import jmespath
9
9
  from jmespath import functions as _jp_funcs
10
10
 
11
- from j_perm.utils.pointers import maybe_slice
12
-
13
11
  # =============================================================================
14
12
  # Types
15
13
  # =============================================================================
@@ -295,6 +293,6 @@ class TemplateSubstitutor:
295
293
  # 4) JSON Pointer fallback
296
294
  pointer = "/" + expr.lstrip("/")
297
295
  try:
298
- return maybe_slice(pointer, data) # type: ignore[arg-type]
296
+ return engine.pointer_manager.maybe_slice(pointer, data) # type: ignore[arg-type]
299
297
  except Exception:
300
298
  return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: j-perm
3
- Version: 0.2.1.1
3
+ Version: 0.2.2
4
4
  Summary: json permutation library
5
5
  Author-email: Roman <kuschanow@gmail.com>
6
6
  License: MIT
@@ -0,0 +1,39 @@
1
+ j_perm/__init__.py,sha256=81aLdcmlUg51R6xR-VXVDDUeM87ezy3ZuiLpblHZ_wk,873
2
+ j_perm/engine.py,sha256=VFbzrywAucQ2VlIqSulstVe9zsEGRdHkZyhJEzWwPSw,4036
3
+ j_perm/normalizer.py,sha256=zxWtARRNuzS-zgFuB40dqU0oaUUk8PLKJNOPNb5wbRw,2672
4
+ j_perm/op_handler.py,sha256=h28thz_18DwZTb9IZtTd6kfsZj7hN4UsmU4uf3aMYpo,1649
5
+ j_perm/pointers.py,sha256=Czhq9vre_HnxhT1iOs8cDcKdCvEum5_YdvaEzoZ3iTY,3205
6
+ j_perm/special_resolver.py,sha256=khRVWXrE3Vch1gbxsfFwj9JQ37pZ-_ojMeh-G2Vv7bs,4032
7
+ j_perm/subst.py,sha256=aIkx5yi98tb2C5m1iOxvmLGiCYZXobgyT0-rsPssJ78,9778
8
+ j_perm/casters/__init__.py,sha256=mD49oMEyj6oDfSKXEJ8DbnmqkSypfEEg3VMI_rfaK-4,114
9
+ j_perm/casters/_bool.py,sha256=qRsT7IcFBApD09elKUyUUaZmfePSIsOsKQHQHsgnHsw,230
10
+ j_perm/casters/_float.py,sha256=C4r-h6zbkjmQnoEdE2RDMhSkW9oGrvxbQngJZ2T7_tU,153
11
+ j_perm/casters/_int.py,sha256=f1BKqsULiG6Puov1qcGS_inSnv0hZtQ0deQEMP0v0i4,145
12
+ j_perm/casters/_str.py,sha256=v1_BD1_hPbOtvO5CKYAlNEGbMhpR56eKCnV2a2Q4kGU,145
13
+ j_perm/constructs/__init__.py,sha256=TTUPSMyvj8HSfPikrFqXaFsechc9aOIbjtVjy4TOolE,50
14
+ j_perm/constructs/eval.py,sha256=UzjZK27UAzsl3s26Y3RWBPhuKX1Az0fK6xk-cgpS8pQ,452
15
+ j_perm/constructs/ref.py,sha256=qp1u7737LYDU-73DTP5fn-Q-X0kSNMlL3247vkYSTOQ,626
16
+ j_perm/funcs/__init__.py,sha256=8yIafxhCH5B7jXrsautQEtl4Qt8RcUK7IWNniORj9ow,31
17
+ j_perm/funcs/subtract.py,sha256=8W49TsrnIU4EVjS8tWQY2GXlX2nAaQ1O9O1JlrVYdIw,288
18
+ j_perm/ops/__init__.py,sha256=j_U4Aq0iwEvZOF0jqMmlQA0NisJsHNJWzqkfyMWuHFA,364
19
+ j_perm/ops/_assert.py,sha256=Z3FaNTHwwM8yey0cpbOrtJpQdBCsqASdU8KH2dymisU,761
20
+ j_perm/ops/_assert_d.py,sha256=lPyvheXFjz955z-AvmZRCjcl7a8UGGZuNneiZp3yVIA,771
21
+ j_perm/ops/_exec.py,sha256=_JhHyeFsRlFEwkrCipRyvzVLrScSHI595eW4lIrmNc0,1895
22
+ j_perm/ops/_if.py,sha256=DJPrNVnxnUSfx8hcLtIaJP51MyK3zTOGtkVrbIFKlZE,1572
23
+ j_perm/ops/copy.py,sha256=C3FUXxs1wBqMhu7NcpvxoBABMQK3DGfbaitqN7TYMqg,1092
24
+ j_perm/ops/copy_d.py,sha256=ES5fYV-gbBZDK6kMew1jFb_lAkeUbpPAp2s3KoVBzqo,999
25
+ j_perm/ops/delete.py,sha256=CuTHH1o7hWLbrdz6kvWFCWEirQEuKPpnkYtL-FytygI,886
26
+ j_perm/ops/distinct.py,sha256=IK1edAwXMizLZ-3JvS2RvJ14DAJHR03Ji4Tzs0191Ao,1050
27
+ j_perm/ops/foreach.py,sha256=E6YozlfwMi05yZI7dVTzy5Nh9QXfOpyRpfDB4wP4kYQ,1407
28
+ j_perm/ops/replace_root.py,sha256=FFyc-95n3kTzcOXrnjwDdvwOnKNitXKb_1F25MMnXd8,445
29
+ j_perm/ops/set.py,sha256=TfTkKNhPEpe58Vq8oftRTH23PEnRVpPF8QGemkUMi5E,1870
30
+ j_perm/ops/update.py,sha256=rMeNYzjef_-d4uzO5PXHbpjMHcejNiNTEhLetxo3sxU,2433
31
+ j_perm/schema/__init__.py,sha256=mhEbGdi1MgLeEm1IL8-tkTtbIdrdlvQi22sBr7vCUqg,3392
32
+ j_perm/shorthands/__init__.py,sha256=zvsu15iExYtUrct6Ob4IRs6Ao46PoZaCKVIUhMBY4Dk,117
33
+ j_perm/shorthands/_assert.py,sha256=iRvuUGlN5Bj9G5Bo-aXUa4MQujgmrR3N-PhDeee6xcY,555
34
+ j_perm/shorthands/assign_or_append.py,sha256=TsSzaQXb5qoKtY6tvx_skHob-695Zii5roUfXltznAQ,621
35
+ j_perm/shorthands/delete.py,sha256=PZeTRcP6-Q3SdbdyruWWXtMJ9mTnz1CBCHiOpHNI06Q,311
36
+ j_perm-0.2.2.dist-info/METADATA,sha256=0YW5JaEOhCYLcyVtDrHLdFCjzritqG13H1zoXvtdCr4,17658
37
+ j_perm-0.2.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
38
+ j_perm-0.2.2.dist-info/top_level.txt,sha256=yveBxREqVn9DliNwmen1QWoxR0uta7bU5giS1CCffRI,7
39
+ j_perm-0.2.2.dist-info/RECORD,,
j_perm/utils/__init__.py DELETED
File without changes
j_perm/utils/pointers.py DELETED
@@ -1,108 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import re
4
- from typing import Any, Mapping, MutableMapping, List, Tuple
5
-
6
- _SLICE_RE = re.compile(r"(.+)\[(-?\d*):(-?\d*)]$")
7
-
8
-
9
- def _decode(tok: str) -> str:
10
- """Decode a single JSON Pointer token, handling RFC6901-style escapes."""
11
- return (
12
- tok.replace("~0", "~")
13
- .replace("~1", "/")
14
- .replace("~2", "$")
15
- .replace("~3", ".")
16
- )
17
-
18
-
19
- def jptr_get(doc: Any, ptr: str) -> Any:
20
- """Read value by JSON Pointer, supporting root and '..' segments."""
21
- if ptr in ("", "/", "."):
22
- return doc
23
-
24
- tokens = ptr.lstrip("/").split("/")
25
- cur: Any = doc
26
- parents: List[Tuple[Any, Any]] = []
27
-
28
- for raw_tok in tokens:
29
- if raw_tok == "..":
30
- if parents:
31
- cur, _ = parents.pop()
32
- else:
33
- cur = doc
34
- continue
35
-
36
- key = _decode(raw_tok)
37
-
38
- if isinstance(cur, (list, tuple)):
39
- idx = int(key)
40
- parents.append((cur, idx))
41
- cur = cur[idx]
42
- else:
43
- parents.append((cur, key))
44
- cur = cur[key]
45
-
46
- return cur
47
-
48
-
49
- def maybe_slice(ptr: str, src: Mapping[str, Any]) -> Any:
50
- """Resolve a pointer and optional Python-style slice suffix '[start:end]' for arrays."""
51
- m = _SLICE_RE.match(ptr)
52
- if m:
53
- base, s, e = m.groups()
54
- seq = jptr_get(src, base)
55
- if not isinstance(seq, (list, tuple)):
56
- raise TypeError(f"{base} is not a list (slice requested)")
57
-
58
- start = int(s) if s else None
59
- end = int(e) if e else None
60
- return seq[start:end]
61
-
62
- return jptr_get(src, ptr)
63
-
64
-
65
- def jptr_ensure_parent(
66
- doc: MutableMapping[str, Any],
67
- ptr: str,
68
- *,
69
- create: bool = False,
70
- ):
71
- """Return (container, leaf_key) for ptr, optionally creating intermediate nodes."""
72
- raw_parts = ptr.lstrip("/").split("/")
73
- parts: List[str] = []
74
-
75
- for raw in raw_parts:
76
- if raw == "..":
77
- if parts:
78
- parts.pop()
79
- continue
80
- parts.append(raw)
81
-
82
- if not parts:
83
- return doc, ""
84
-
85
- cur: Any = doc
86
-
87
- for raw in parts[:-1]:
88
- token = _decode(raw)
89
-
90
- if isinstance(cur, list):
91
- idx = int(token)
92
- if idx >= len(cur):
93
- if create:
94
- while idx >= len(cur):
95
- cur.append({})
96
- else:
97
- raise IndexError(f"{ptr}: index {idx} out of range")
98
- cur = cur[idx]
99
- else:
100
- if token not in cur:
101
- if create:
102
- cur[token] = {}
103
- else:
104
- raise KeyError(f"{ptr}: missing key '{token}'")
105
- cur = cur[token]
106
-
107
- leaf = _decode(parts[-1])
108
- return cur, leaf
@@ -1,40 +0,0 @@
1
- j_perm/__init__.py,sha256=81aLdcmlUg51R6xR-VXVDDUeM87ezy3ZuiLpblHZ_wk,873
2
- j_perm/engine.py,sha256=iaUxB7EWcqvWsP4Z8z49a6-atX9br1tTC-WlZVrVo-A,3923
3
- j_perm/normalizer.py,sha256=50pff5j3sTrCu2Fp_SW6m99qwt88CladpYlWpQ3c-ac,2671
4
- j_perm/op_handler.py,sha256=h28thz_18DwZTb9IZtTd6kfsZj7hN4UsmU4uf3aMYpo,1649
5
- j_perm/special_resolver.py,sha256=khRVWXrE3Vch1gbxsfFwj9JQ37pZ-_ojMeh-G2Vv7bs,4032
6
- j_perm/subst.py,sha256=oW21Gs2nTEQLcOC_xMKzeuZFtfNvnB2QZAIWl7U4TSg,9802
7
- j_perm/casters/__init__.py,sha256=mD49oMEyj6oDfSKXEJ8DbnmqkSypfEEg3VMI_rfaK-4,114
8
- j_perm/casters/_bool.py,sha256=qRsT7IcFBApD09elKUyUUaZmfePSIsOsKQHQHsgnHsw,230
9
- j_perm/casters/_float.py,sha256=C4r-h6zbkjmQnoEdE2RDMhSkW9oGrvxbQngJZ2T7_tU,153
10
- j_perm/casters/_int.py,sha256=f1BKqsULiG6Puov1qcGS_inSnv0hZtQ0deQEMP0v0i4,145
11
- j_perm/casters/_str.py,sha256=v1_BD1_hPbOtvO5CKYAlNEGbMhpR56eKCnV2a2Q4kGU,145
12
- j_perm/constructs/__init__.py,sha256=TTUPSMyvj8HSfPikrFqXaFsechc9aOIbjtVjy4TOolE,50
13
- j_perm/constructs/eval.py,sha256=UzjZK27UAzsl3s26Y3RWBPhuKX1Az0fK6xk-cgpS8pQ,452
14
- j_perm/constructs/ref.py,sha256=GtR2hpENev9k1lsx3mHGM8956vBfrPUgHm3IydYr-_I,644
15
- j_perm/funcs/__init__.py,sha256=8yIafxhCH5B7jXrsautQEtl4Qt8RcUK7IWNniORj9ow,31
16
- j_perm/funcs/subtract.py,sha256=8W49TsrnIU4EVjS8tWQY2GXlX2nAaQ1O9O1JlrVYdIw,288
17
- j_perm/ops/__init__.py,sha256=j_U4Aq0iwEvZOF0jqMmlQA0NisJsHNJWzqkfyMWuHFA,364
18
- j_perm/ops/_assert.py,sha256=O7MFxW3FDCglPMx-tBwi67k2Wd-Mds996AQdeGLbM6Q,773
19
- j_perm/ops/_assert_d.py,sha256=xEjqBryCbzBpkzYhwRZht7-uyXv7XaCkEcRt6sjwE7k,783
20
- j_perm/ops/_exec.py,sha256=HaFy__49QXnxYNbh1IdIu8ZQoWlQsrms5HgyRN5lV6o,1913
21
- j_perm/ops/_if.py,sha256=DNYp0j3-3YYMIR_CcDM3Ai0CpW2Qt4SYtKxk-9onu8c,1590
22
- j_perm/ops/copy.py,sha256=fV2rE92JyTRqo91GjXwWucklDR1T1ZcFHHbxG1F8S9g,1110
23
- j_perm/ops/copy_d.py,sha256=2SGHoq4vaD79diJos_oO3pvZvC_XrQorxhXAgZ5l09E,1017
24
- j_perm/ops/delete.py,sha256=7SzLE9W_dlmcLOVzKjOzIFLSAHf9nGlagbhbwIH_PmI,916
25
- j_perm/ops/distinct.py,sha256=RoVIIRNm7C9iAjcPZHpoMfgKw6pGx7nuLkYwruhHeYY,1036
26
- j_perm/ops/foreach.py,sha256=6tEQ9PyiWBvrm0eANg18p5hV-OvIiL2O1rdqWOC18tQ,1425
27
- j_perm/ops/replace_root.py,sha256=FFyc-95n3kTzcOXrnjwDdvwOnKNitXKb_1F25MMnXd8,445
28
- j_perm/ops/set.py,sha256=-kFFgHxeq65K5vLzDe6PhUoLT-ksoZYUVL1Jxf8bRA0,1882
29
- j_perm/ops/update.py,sha256=gvJTh3vS4zD-lpaqN23w5OO3hTtkSdu8RPy0V8r8Rwg,2471
30
- j_perm/schema/__init__.py,sha256=mhEbGdi1MgLeEm1IL8-tkTtbIdrdlvQi22sBr7vCUqg,3392
31
- j_perm/shorthands/__init__.py,sha256=zvsu15iExYtUrct6Ob4IRs6Ao46PoZaCKVIUhMBY4Dk,117
32
- j_perm/shorthands/_assert.py,sha256=iRvuUGlN5Bj9G5Bo-aXUa4MQujgmrR3N-PhDeee6xcY,555
33
- j_perm/shorthands/assign_or_append.py,sha256=TsSzaQXb5qoKtY6tvx_skHob-695Zii5roUfXltznAQ,621
34
- j_perm/shorthands/delete.py,sha256=PZeTRcP6-Q3SdbdyruWWXtMJ9mTnz1CBCHiOpHNI06Q,311
35
- j_perm/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
- j_perm/utils/pointers.py,sha256=X1HSCag4t-qq5zTvBMRAlBKXwpHVNNZYJrdJRtyEr4g,2788
37
- j_perm-0.2.1.1.dist-info/METADATA,sha256=zwwrX08mxWxT5sMGLkh4PaLBVs7FMspDzwhcqj8sfpg,17660
38
- j_perm-0.2.1.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
39
- j_perm-0.2.1.1.dist-info/top_level.txt,sha256=yveBxREqVn9DliNwmen1QWoxR0uta7bU5giS1CCffRI,7
40
- j_perm-0.2.1.1.dist-info/RECORD,,