moat-lib-path 0.3.7__tar.gz → 0.4.0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: moat-lib-path
3
- Version: 0.3.7
3
+ Version: 0.4.0
4
4
  Summary: Hierarchical path representation and manipulation for MoaT
5
5
  Maintainer-email: Matthias Urlichs <matthias@urlichs.de>
6
6
  Project-URL: homepage, https://m-o-a-t.org
@@ -1,3 +1,9 @@
1
+ moat-lib-path (0.4.0-1) unstable; urgency=medium
2
+
3
+ * New release for 26.4.40
4
+
5
+ -- Matthias Urlichs <matthias@urlichs.de> Sat, 17 Oct 2026 14:39:43 +0200
6
+
1
7
  moat-lib-path (0.3.7-1) unstable; urgency=medium
2
8
 
3
9
  * New release for 26.4.27
@@ -22,7 +22,7 @@ name = "moat-lib-path"
22
22
  maintainers = [{email = "matthias@urlichs.de",name = "Matthias Urlichs"}]
23
23
  description='Hierarchical path representation and manipulation for MoaT'
24
24
  readme = "README.md"
25
- version = "0.3.7"
25
+ version = "0.4.0"
26
26
 
27
27
  [project.urls]
28
28
  homepage = "https://m-o-a-t.org"
@@ -21,6 +21,7 @@ from ._impl import (
21
21
  RootPath,
22
22
  S_Root,
23
23
  logger_for,
24
+ norm_root,
24
25
  path_eval,
25
26
  set_root,
26
27
  )
@@ -39,6 +40,7 @@ __all__ = [
39
40
  "RootPath",
40
41
  "S_Root",
41
42
  "logger_for",
43
+ "norm_root",
42
44
  "path_eval",
43
45
  "set_root",
44
46
  ]
@@ -78,13 +78,31 @@ _PartRE = re.compile("[^:._]+|_|:|\\.")
78
78
  _RTagRE = re.compile("^:m[^:._]+:$")
79
79
 
80
80
 
81
+ def norm_root(root: Path) -> Path:
82
+ """Flatten a possibly ``:R``-prefixed path into a plain one.
83
+
84
+ Constructing a path that equals the ambient root (e.g. ``P("a.b")``
85
+ while ``Root`` is ``a.b``) absorbs the root as a ``:R`` prefix.
86
+ Storing such a self-referential path as a root would serialize to
87
+ the empty string, so roots must always be normalized to plain
88
+ element tuples.
89
+ """
90
+ if root._prefix is None: # noqa: SLF001
91
+ return root
92
+ pref = root._prefix # noqa: SLF001
93
+ if not isinstance(pref, RootPath):
94
+ # Explicitly-relative path (``:@``): not a root absorption.
95
+ return root
96
+ return Path(*pref._data, *root._data, _warn=False) # noqa: SLF001
97
+
98
+
81
99
  def set_root(cfg) -> None:
82
100
  """
83
101
  Utility to force-set the root global.
84
102
 
85
103
  Used for testing without a "proper" context.
86
104
  """
87
- Root.set(cfg.root)
105
+ Root.set(norm_root(cfg.root))
88
106
 
89
107
 
90
108
  @total_ordering
@@ -1164,80 +1182,7 @@ path_eval = _eval.eval
1164
1182
  # Here we declare our bunch of "root" variables.
1165
1183
 
1166
1184
 
1167
- class _NoResetToken:
1168
- """Token returned by :meth:`Var.set`.
1169
-
1170
- ``Var`` has no context to restore, so unlike a real ``ContextVar`` token
1171
- this carries no state: its only job is to be recognisable to
1172
- :meth:`Var.reset` so the ``set``/``reset`` protocol driven by ``ctx_as``
1173
- works uniformly for both ``ContextVar`` and ``Var``.
1174
- """
1175
-
1176
- __slots__ = ()
1177
-
1178
- def __repr__(self) -> str:
1179
- return "<Var no-reset token>"
1180
-
1181
-
1182
- _VAR_SET_TOKEN = _NoResetToken()
1183
-
1184
-
1185
- class Var:
1186
- """
1187
- This mimics a ContextVar but without the context.
1188
- """
1189
-
1190
- def __init__(self, name, default=NotGiven) -> None:
1191
- self.name = name
1192
- self.default = default
1193
- self.data = NotGiven
1194
-
1195
- def get(self):
1196
- "get current value"
1197
- if self.data is NotGiven:
1198
- raise ValueError("Not set")
1199
- return self.data
1200
-
1201
- def set(self, val, *, force: bool = False):
1202
- "set current value"
1203
- # If the root is a.b.c, a new identical value will arrive as an
1204
- # empty path with a root of a.b.c. That's bad. Thus silently don't
1205
- # update in that case.
1206
- #
1207
- # We detect that case structurally.
1208
- #
1209
- # Match by the RootPath's *key* ("R"), not by ``_var is self``:
1210
- # the ``RootPath`` embedded in @val may hold a stale ``Var`` (a
1211
- # second ``Root`` instance created, if the namespace-packaged
1212
- # ``moat.lib.path._impl`` is loaded more than once), so identity
1213
- # would fail even though @val denotes the same root.
1214
- if (
1215
- not force
1216
- and self.data is not NotGiven
1217
- and isinstance(val, Path)
1218
- and isinstance(val._prefix, RootPath) # noqa:SLF001
1219
- and val._prefix._key == "R" # noqa:SLF001
1220
- and not len(val._data) # noqa:SLF001
1221
- ):
1222
- return _VAR_SET_TOKEN
1223
- if not force and self.data is not NotGiven:
1224
- if self.data.slashed != val.slashed:
1225
- raise ValueError("Already set", self.data, val)
1226
- return _VAR_SET_TOKEN
1227
- self.data = val
1228
- return _VAR_SET_TOKEN
1229
-
1230
- def __bool__(self) -> bool:
1231
- "check if value is set"
1232
- return self.data is not NotGiven
1233
-
1234
- def reset(self, token) -> None:
1235
- "reset value; no-op"
1236
- if token is not _VAR_SET_TOKEN:
1237
- raise ValueError(token)
1238
-
1239
-
1240
- Root = Var("Root", default=None)
1185
+ Root = ContextVar[Path | None]("Root", default=None)
1241
1186
 
1242
1187
 
1243
1188
  class RootPath(Path):
@@ -1250,7 +1195,7 @@ class RootPath(Path):
1250
1195
 
1251
1196
  _mark = ""
1252
1197
 
1253
- def __init__(self, key: str, var: ContextVar[Path | None] | Var) -> None:
1198
+ def __init__(self, key: str, var: ContextVar[Path | None]) -> None:
1254
1199
  self._key = key
1255
1200
  self._var = var
1256
1201
 
@@ -1269,10 +1214,7 @@ class RootPath(Path):
1269
1214
 
1270
1215
  def __bool__(self) -> bool:
1271
1216
  "check if the contextvar is set"
1272
- if isinstance(self._var, Var):
1273
- return bool(self._var)
1274
- p = self._var.get()
1275
- return p is not None
1217
+ return self._var.get() is not None
1276
1218
 
1277
1219
  @property
1278
1220
  def _data(self) -> PathTuple: # pyright:ignore
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: moat-lib-path
3
- Version: 0.3.7
3
+ Version: 0.4.0
4
4
  Summary: Hierarchical path representation and manipulation for MoaT
5
5
  Maintainer-email: Matthias Urlichs <matthias@urlichs.de>
6
6
  Project-URL: homepage, https://m-o-a-t.org
File without changes
File without changes
File without changes
File without changes