moat-lib-path 0.3.6__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.
- {moat_lib_path-0.3.6/src/moat_lib_path.egg-info → moat_lib_path-0.4.0}/PKG-INFO +1 -1
- {moat_lib_path-0.3.6 → moat_lib_path-0.4.0}/debian/changelog +12 -0
- {moat_lib_path-0.3.6 → moat_lib_path-0.4.0}/pyproject.toml +1 -1
- {moat_lib_path-0.3.6 → moat_lib_path-0.4.0}/src/moat/lib/path/__init__.py +2 -0
- {moat_lib_path-0.3.6 → moat_lib_path-0.4.0}/src/moat/lib/path/_impl.py +32 -84
- {moat_lib_path-0.3.6 → moat_lib_path-0.4.0/src/moat_lib_path.egg-info}/PKG-INFO +1 -1
- {moat_lib_path-0.3.6 → moat_lib_path-0.4.0}/LICENSE.txt +0 -0
- {moat_lib_path-0.3.6 → moat_lib_path-0.4.0}/Makefile +0 -0
- {moat_lib_path-0.3.6 → moat_lib_path-0.4.0}/README.md +0 -0
- {moat_lib_path-0.3.6 → moat_lib_path-0.4.0}/debian/.gitignore +0 -0
- {moat_lib_path-0.3.6 → moat_lib_path-0.4.0}/debian/control +0 -0
- {moat_lib_path-0.3.6 → moat_lib_path-0.4.0}/debian/rules +0 -0
- {moat_lib_path-0.3.6 → moat_lib_path-0.4.0}/setup.cfg +0 -0
- {moat_lib_path-0.3.6 → moat_lib_path-0.4.0}/src/moat_lib_path.egg-info/SOURCES.txt +0 -0
- {moat_lib_path-0.3.6 → moat_lib_path-0.4.0}/src/moat_lib_path.egg-info/dependency_links.txt +0 -0
- {moat_lib_path-0.3.6 → moat_lib_path-0.4.0}/src/moat_lib_path.egg-info/requires.txt +0 -0
- {moat_lib_path-0.3.6 → moat_lib_path-0.4.0}/src/moat_lib_path.egg-info/top_level.txt +0 -0
|
@@ -1,3 +1,15 @@
|
|
|
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
|
+
|
|
7
|
+
moat-lib-path (0.3.7-1) unstable; urgency=medium
|
|
8
|
+
|
|
9
|
+
* New release for 26.4.27
|
|
10
|
+
|
|
11
|
+
-- Matthias Urlichs <matthias@urlichs.de> Sat, 03 Oct 2026 14:53:15 +0200
|
|
12
|
+
|
|
1
13
|
moat-lib-path (0.3.6-1) unstable; urgency=medium
|
|
2
14
|
|
|
3
15
|
* New release for 26.4.26
|
|
@@ -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.
|
|
25
|
+
version = "0.4.0"
|
|
26
26
|
|
|
27
27
|
[project.urls]
|
|
28
28
|
homepage = "https://m-o-a-t.org"
|
|
@@ -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
|
|
@@ -196,14 +214,20 @@ class Path(Sequence[PathElem]):
|
|
|
196
214
|
if mark:
|
|
197
215
|
warnings.warn("Marking a path is deprecated")
|
|
198
216
|
|
|
199
|
-
if
|
|
217
|
+
if not a:
|
|
218
|
+
pass
|
|
219
|
+
elif decoded and isinstance(a[0], RootPath) and prefix is None:
|
|
220
|
+
prefix = a[0]
|
|
221
|
+
a = a[1:]
|
|
222
|
+
elif isinstance(a[0], Path):
|
|
223
|
+
if len(a) > 1:
|
|
224
|
+
raise ValueError("Can't build a path this way")
|
|
225
|
+
a = a[0].as_tuple()
|
|
226
|
+
elif len(a) != 1 and _warn:
|
|
200
227
|
warnings.warn(
|
|
201
228
|
"Call 'Path.build(args)', not 'Path(*args)'", DeprecationWarning, stacklevel=2
|
|
202
229
|
)
|
|
203
230
|
|
|
204
|
-
if decoded and a and isinstance(a[0], RootPath) and prefix is None:
|
|
205
|
-
prefix = a[0]
|
|
206
|
-
a = a[1:]
|
|
207
231
|
for x in a:
|
|
208
232
|
if not isinstance(x, PathElemI): # pyright:ignore[reportArgumentType]
|
|
209
233
|
raise TypeError(f"{x!r} cannot be in a path")
|
|
@@ -1158,80 +1182,7 @@ path_eval = _eval.eval
|
|
|
1158
1182
|
# Here we declare our bunch of "root" variables.
|
|
1159
1183
|
|
|
1160
1184
|
|
|
1161
|
-
|
|
1162
|
-
"""Token returned by :meth:`Var.set`.
|
|
1163
|
-
|
|
1164
|
-
``Var`` has no context to restore, so unlike a real ``ContextVar`` token
|
|
1165
|
-
this carries no state: its only job is to be recognisable to
|
|
1166
|
-
:meth:`Var.reset` so the ``set``/``reset`` protocol driven by ``ctx_as``
|
|
1167
|
-
works uniformly for both ``ContextVar`` and ``Var``.
|
|
1168
|
-
"""
|
|
1169
|
-
|
|
1170
|
-
__slots__ = ()
|
|
1171
|
-
|
|
1172
|
-
def __repr__(self) -> str:
|
|
1173
|
-
return "<Var no-reset token>"
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
_VAR_SET_TOKEN = _NoResetToken()
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
class Var:
|
|
1180
|
-
"""
|
|
1181
|
-
This mimics a ContextVar but without the context.
|
|
1182
|
-
"""
|
|
1183
|
-
|
|
1184
|
-
def __init__(self, name, default=NotGiven) -> None:
|
|
1185
|
-
self.name = name
|
|
1186
|
-
self.default = default
|
|
1187
|
-
self.data = NotGiven
|
|
1188
|
-
|
|
1189
|
-
def get(self):
|
|
1190
|
-
"get current value"
|
|
1191
|
-
if self.data is NotGiven:
|
|
1192
|
-
raise ValueError("Not set")
|
|
1193
|
-
return self.data
|
|
1194
|
-
|
|
1195
|
-
def set(self, val, *, force: bool = False):
|
|
1196
|
-
"set current value"
|
|
1197
|
-
# If the root is a.b.c, a new identical value will arrive as an
|
|
1198
|
-
# empty path with a root of a.b.c. That's bad. Thus silently don't
|
|
1199
|
-
# update in that case.
|
|
1200
|
-
#
|
|
1201
|
-
# We detect that case structurally.
|
|
1202
|
-
#
|
|
1203
|
-
# Match by the RootPath's *key* ("R"), not by ``_var is self``:
|
|
1204
|
-
# the ``RootPath`` embedded in @val may hold a stale ``Var`` (a
|
|
1205
|
-
# second ``Root`` instance created, if the namespace-packaged
|
|
1206
|
-
# ``moat.lib.path._impl`` is loaded more than once), so identity
|
|
1207
|
-
# would fail even though @val denotes the same root.
|
|
1208
|
-
if (
|
|
1209
|
-
not force
|
|
1210
|
-
and self.data is not NotGiven
|
|
1211
|
-
and isinstance(val, Path)
|
|
1212
|
-
and isinstance(val._prefix, RootPath) # noqa:SLF001
|
|
1213
|
-
and val._prefix._key == "R" # noqa:SLF001
|
|
1214
|
-
and not len(val._data) # noqa:SLF001
|
|
1215
|
-
):
|
|
1216
|
-
return _VAR_SET_TOKEN
|
|
1217
|
-
if not force and self.data is not NotGiven:
|
|
1218
|
-
if self.data.slashed != val.slashed:
|
|
1219
|
-
raise ValueError("Already set", self.data, val)
|
|
1220
|
-
return _VAR_SET_TOKEN
|
|
1221
|
-
self.data = val
|
|
1222
|
-
return _VAR_SET_TOKEN
|
|
1223
|
-
|
|
1224
|
-
def __bool__(self) -> bool:
|
|
1225
|
-
"check if value is set"
|
|
1226
|
-
return self.data is not NotGiven
|
|
1227
|
-
|
|
1228
|
-
def reset(self, token) -> None:
|
|
1229
|
-
"reset value; no-op"
|
|
1230
|
-
if token is not _VAR_SET_TOKEN:
|
|
1231
|
-
raise ValueError(token)
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
Root = Var("Root", default=None)
|
|
1185
|
+
Root = ContextVar[Path | None]("Root", default=None)
|
|
1235
1186
|
|
|
1236
1187
|
|
|
1237
1188
|
class RootPath(Path):
|
|
@@ -1244,7 +1195,7 @@ class RootPath(Path):
|
|
|
1244
1195
|
|
|
1245
1196
|
_mark = ""
|
|
1246
1197
|
|
|
1247
|
-
def __init__(self, key: str, var: ContextVar[Path | None]
|
|
1198
|
+
def __init__(self, key: str, var: ContextVar[Path | None]) -> None:
|
|
1248
1199
|
self._key = key
|
|
1249
1200
|
self._var = var
|
|
1250
1201
|
|
|
@@ -1263,10 +1214,7 @@ class RootPath(Path):
|
|
|
1263
1214
|
|
|
1264
1215
|
def __bool__(self) -> bool:
|
|
1265
1216
|
"check if the contextvar is set"
|
|
1266
|
-
|
|
1267
|
-
return bool(self._var)
|
|
1268
|
-
p = self._var.get()
|
|
1269
|
-
return p is not None
|
|
1217
|
+
return self._var.get() is not None
|
|
1270
1218
|
|
|
1271
1219
|
@property
|
|
1272
1220
|
def _data(self) -> PathTuple: # pyright:ignore
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|