nab-markersets 0.0.16__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.
@@ -0,0 +1,22 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ .pytest_cache/
7
+ .hypothesis/
8
+ .coverage*
9
+ .ruff_cache/
10
+ .venv/
11
+ .hatch/
12
+ .nox/
13
+ docs/_build/
14
+
15
+ *token*.txt
16
+ *.pypirc
17
+ .pypirc
18
+
19
+ # Profiling artefacts. By convention these live in `profiling/` at
20
+ # the workspace root and never inside `docs/`, so the Sphinx build
21
+ # never has to scan them.
22
+ profiling/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Damian Shaw
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,101 @@
1
+ Metadata-Version: 2.4
2
+ Name: nab-markersets
3
+ Version: 0.0.16
4
+ Summary: PEP 508 marker algebra: markers as sets of environments
5
+ Project-URL: Homepage, https://github.com/notatallshaw/nab
6
+ Project-URL: Documentation, https://nab.readthedocs.io/
7
+ Project-URL: Issues, https://github.com/notatallshaw/nab/issues
8
+ Project-URL: Source, https://github.com/notatallshaw/nab
9
+ Project-URL: Changelog, https://github.com/notatallshaw/nab/releases
10
+ Author-email: Damian Shaw <damian.peter.shaw@gmail.com>
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.10
22
+ Provides-Extra: nab-vendored-packaging
23
+ Requires-Dist: nab-provider==0.0.16; extra == 'nab-vendored-packaging'
24
+ Provides-Extra: packaging
25
+ Requires-Dist: packaging>=26.3; extra == 'packaging'
26
+ Description-Content-Type: text/markdown
27
+
28
+ # nab-markersets
29
+
30
+ A PEP 508 marker read as the set of environments it selects. `packaging`
31
+ answers "does this marker hold here"; this answers "can these two ever both
32
+ hold", "does one imply the other", and "is this a contradiction".
33
+
34
+ **Experimental.** Anything here can change in any release, so pin an exact
35
+ version. The intent is to land this algebra in `packaging` itself, and the
36
+ shape below is what that proposal is being tried against; the discussion is
37
+ [pypa/packaging#448](https://github.com/pypa/packaging/issues/448).
38
+
39
+ ```pycon
40
+ >>> from nab_markersets.markersets import MarkerSet
41
+ >>> old = MarkerSet.from_marker('python_version < "3.11"')
42
+ >>> new = MarkerSet.from_marker('python_version >= "3.12"')
43
+ >>> old.is_disjoint(new)
44
+ True
45
+ ```
46
+
47
+ A set also holds what a marker string cannot: the full set of an absent
48
+ marker, the empty set of a contradiction, and complements the grammar cannot
49
+ spell. `witness` returns a point in the set, which is what separates two
50
+ markers that look like one constraint.
51
+
52
+ ```pycon
53
+ >>> minor = MarkerSet.from_marker('python_version >= "3.11"')
54
+ >>> exact = MarkerSet.from_marker('python_full_version >= "3.11.0"')
55
+ >>> minor.equivalent(exact)
56
+ False
57
+ >>> (minor & ~exact).witness()["python_full_version"]
58
+ '3.11.0.dev0'
59
+ ```
60
+
61
+ ## Installing
62
+
63
+ The engine runs on `packaging`'s parse tree and its single-atom evaluator, and
64
+ two copies of `packaging` exist: the released one, and the fork
65
+ [`nab`](https://pypi.org/project/nab/) vendors. An extra picks which.
66
+
67
+ ```bash
68
+ pip install "nab-markersets[packaging]"
69
+ pip install "nab-markersets[nab-vendored-packaging]"
70
+ ```
71
+
72
+ The first copy at `packaging>=26.3` is bound, so with both installed the fork
73
+ wins and a `Marker` built inside nab keeps the class the algebra tests against.
74
+ A `Marker` from the other copy is accepted too. With nothing that new,
75
+ importing `nab_markersets.markersets` fails and says what it found.
76
+
77
+ ## When to use it
78
+
79
+ Whether two lock entries can both apply, whether a dependency is reachable
80
+ inside your `requires-python`, or what a marker still says once you fix the
81
+ platform. The guide walks through those, and through what the decisions do not
82
+ decide:
83
+ <https://nab.readthedocs.io/en/stable/how-to/reason-about-markers.html>
84
+
85
+ ## The public API
86
+
87
+ The supported API is the module paths below. Everything else in the package is
88
+ internal and may be renamed or relocated in any release.
89
+
90
+ ```text
91
+ nab_markersets.errors IntractableMarkerSet, UnserializableMarkerSet
92
+ nab_markersets.markersets DecisionStore, MarkerSet, variable_names
93
+ ```
94
+
95
+ The package root binds no names, so importing `nab_markersets` pulls in no
96
+ submodules.
97
+
98
+ Two things before you call it. A `MarkerSet` comes from `from_marker`, `full`
99
+ or `empty`, so `pickle.loads` fails on one: the constructor it reaches for
100
+ refuses. And `==` is structural, over the tree the set was built from, where
101
+ `equivalent` is the semantic test.
@@ -0,0 +1,74 @@
1
+ # nab-markersets
2
+
3
+ A PEP 508 marker read as the set of environments it selects. `packaging`
4
+ answers "does this marker hold here"; this answers "can these two ever both
5
+ hold", "does one imply the other", and "is this a contradiction".
6
+
7
+ **Experimental.** Anything here can change in any release, so pin an exact
8
+ version. The intent is to land this algebra in `packaging` itself, and the
9
+ shape below is what that proposal is being tried against; the discussion is
10
+ [pypa/packaging#448](https://github.com/pypa/packaging/issues/448).
11
+
12
+ ```pycon
13
+ >>> from nab_markersets.markersets import MarkerSet
14
+ >>> old = MarkerSet.from_marker('python_version < "3.11"')
15
+ >>> new = MarkerSet.from_marker('python_version >= "3.12"')
16
+ >>> old.is_disjoint(new)
17
+ True
18
+ ```
19
+
20
+ A set also holds what a marker string cannot: the full set of an absent
21
+ marker, the empty set of a contradiction, and complements the grammar cannot
22
+ spell. `witness` returns a point in the set, which is what separates two
23
+ markers that look like one constraint.
24
+
25
+ ```pycon
26
+ >>> minor = MarkerSet.from_marker('python_version >= "3.11"')
27
+ >>> exact = MarkerSet.from_marker('python_full_version >= "3.11.0"')
28
+ >>> minor.equivalent(exact)
29
+ False
30
+ >>> (minor & ~exact).witness()["python_full_version"]
31
+ '3.11.0.dev0'
32
+ ```
33
+
34
+ ## Installing
35
+
36
+ The engine runs on `packaging`'s parse tree and its single-atom evaluator, and
37
+ two copies of `packaging` exist: the released one, and the fork
38
+ [`nab`](https://pypi.org/project/nab/) vendors. An extra picks which.
39
+
40
+ ```bash
41
+ pip install "nab-markersets[packaging]"
42
+ pip install "nab-markersets[nab-vendored-packaging]"
43
+ ```
44
+
45
+ The first copy at `packaging>=26.3` is bound, so with both installed the fork
46
+ wins and a `Marker` built inside nab keeps the class the algebra tests against.
47
+ A `Marker` from the other copy is accepted too. With nothing that new,
48
+ importing `nab_markersets.markersets` fails and says what it found.
49
+
50
+ ## When to use it
51
+
52
+ Whether two lock entries can both apply, whether a dependency is reachable
53
+ inside your `requires-python`, or what a marker still says once you fix the
54
+ platform. The guide walks through those, and through what the decisions do not
55
+ decide:
56
+ <https://nab.readthedocs.io/en/stable/how-to/reason-about-markers.html>
57
+
58
+ ## The public API
59
+
60
+ The supported API is the module paths below. Everything else in the package is
61
+ internal and may be renamed or relocated in any release.
62
+
63
+ ```text
64
+ nab_markersets.errors IntractableMarkerSet, UnserializableMarkerSet
65
+ nab_markersets.markersets DecisionStore, MarkerSet, variable_names
66
+ ```
67
+
68
+ The package root binds no names, so importing `nab_markersets` pulls in no
69
+ submodules.
70
+
71
+ Two things before you call it. A `MarkerSet` comes from `from_marker`, `full`
72
+ or `empty`, so `pickle.loads` fails on one: the constructor it reaches for
73
+ refuses. And `==` is structural, over the tree the set was built from, where
74
+ `equivalent` is the semantic test.
@@ -0,0 +1,43 @@
1
+ [project]
2
+ name = "nab-markersets"
3
+ version = "0.0.16"
4
+ description = "PEP 508 marker algebra: markers as sets of environments"
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ license-files = ["LICENSE"]
8
+ authors = [
9
+ { name = "Damian Shaw", email = "damian.peter.shaw@gmail.com" },
10
+ ]
11
+ requires-python = ">=3.10"
12
+ classifiers = [
13
+ "Development Status :: 4 - Beta",
14
+ "Programming Language :: Python :: 3",
15
+ "Programming Language :: Python :: 3.10",
16
+ "Programming Language :: Python :: 3.11",
17
+ "Programming Language :: Python :: 3.12",
18
+ "Programming Language :: Python :: 3.13",
19
+ "Programming Language :: Python :: 3.14",
20
+ "Typing :: Typed",
21
+ ]
22
+
23
+ # Pick the copy of packaging to run on; `nab_markersets._packaging` binds the
24
+ # first of these at the floor. The floor is where the suite has been run, and
25
+ # it is not open below: the engine reads `_parser.parse_marker`, `_parser.Op`,
26
+ # `_parser.Variable`, `_parser.Value`, `_tokenizer.ParserSyntaxError` and
27
+ # `markers._eval_op`, none of which packaging publishes, so a release may move
28
+ # any of them and `test_the_private_packaging_names_the_engine_reaches` is what
29
+ # says whether one did.
30
+ [project.optional-dependencies]
31
+ packaging = ["packaging>=26.3"]
32
+ nab-vendored-packaging = ["nab-provider==0.0.16"]
33
+
34
+ [project.urls]
35
+ Homepage = "https://github.com/notatallshaw/nab"
36
+ Documentation = "https://nab.readthedocs.io/"
37
+ Issues = "https://github.com/notatallshaw/nab/issues"
38
+ Source = "https://github.com/notatallshaw/nab"
39
+ Changelog = "https://github.com/notatallshaw/nab/releases"
40
+
41
+ [build-system]
42
+ requires = ["hatchling"]
43
+ build-backend = "hatchling.build"
@@ -0,0 +1,11 @@
1
+ """PEP 508 marker algebra: a marker as the set of environments it selects.
2
+
3
+ The supported API is the module paths below. Everything else in the package is
4
+ internal and may be renamed or relocated in any release.
5
+
6
+ nab_markersets.errors IntractableMarkerSet, UnserializableMarkerSet
7
+ nab_markersets.markersets DecisionStore, MarkerSet, variable_names
8
+
9
+ The package root binds no names, so importing ``nab_markersets`` pulls in no
10
+ submodules.
11
+ """
@@ -0,0 +1,18 @@
1
+ """Runtime fallback for :func:`typing.override`, so ``typing_extensions`` is not needed.
2
+
3
+ ``override`` runs at class-body time, so unlike the annotation-only helpers it
4
+ cannot hide under ``TYPE_CHECKING``. Looking it up by name rather than by
5
+ interpreter version keeps this free of a version-gated branch.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import typing
11
+ from typing import TYPE_CHECKING
12
+
13
+ __all__ = ["override"]
14
+
15
+ if TYPE_CHECKING:
16
+ from typing_extensions import override
17
+ else:
18
+ override = getattr(typing, "override", lambda method: method)