Metadata-Version: 2.5
Name: nab-markersets
Version: 0.0.17
Summary: PEP 508 marker algebra: markers as sets of environments
Project-URL: Homepage, https://github.com/notatallshaw/nab
Project-URL: Documentation, https://nab.readthedocs.io/
Project-URL: Issues, https://github.com/notatallshaw/nab/issues
Project-URL: Source, https://github.com/notatallshaw/nab
Project-URL: Changelog, https://github.com/notatallshaw/nab/releases
Author-email: Damian Shaw <damian.peter.shaw@gmail.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Typing :: Typed
Requires-Python: >=3.10
Provides-Extra: nab-vendored-packaging
Requires-Dist: nab-provider==0.0.17; extra == 'nab-vendored-packaging'
Provides-Extra: packaging
Requires-Dist: packaging>=26.3; extra == 'packaging'
Description-Content-Type: text/markdown

# nab-markersets

A PEP 508 marker read as the set of environments it selects.
`packaging` answers "does this marker hold here"; this answers "can
these two ever both hold", "does one imply the other", and "is this a
contradiction".

**Experimental.** The API can change in any release, so pin an exact
version.

```pycon
>>> from nab_markersets.markersets import MarkerSet
>>> old = MarkerSet.from_marker('python_version < "3.11"')
>>> new = MarkerSet.from_marker('python_version >= "3.12"')
>>> old.is_disjoint(new)
True
```

`MarkerSet` represents an absent marker as full, a contradiction as
empty, and complements the marker grammar cannot serialize. `witness`
returns a point in the set, which separates two markers that look like
one constraint.

```pycon
>>> minor = MarkerSet.from_marker('python_version >= "3.11"')
>>> exact = MarkerSet.from_marker('python_full_version >= "3.11.0"')
>>> minor.equivalent(exact)
False
>>> (minor & ~exact).witness()["python_full_version"]
'3.11.0.dev0'
```

## Installing

The engine runs on `packaging`'s parse tree and its single-atom
evaluator. Two copies of `packaging` exist: the released one, and the
fork [`nab`](https://pypi.org/project/nab/) vendors. An extra picks
which.

```bash
pip install "nab-markersets[packaging]"
pip install "nab-markersets[nab-vendored-packaging]"
```

The first copy at version 26.3 or newer is used. The vendored fork is
tried first, followed by released `packaging`.

A `Marker` from the other copy is accepted too. If neither copy is new
enough, importing `nab_markersets.markersets` fails and says what it
found.

## When to use it

Whether two lock entries can both apply, whether a dependency is
reachable inside your `requires-python`, or what a marker still says
once you fix the platform. The guide covers those tasks and the limits
of its decisions:
<https://nab.readthedocs.io/en/stable/how-to/reason-about-markers.html>

## The public API

The supported API is the module paths below. Everything else in the
package is internal and may be renamed or relocated in any release.

```text
nab_markersets.errors       IntractableMarkerSet, UnserializableMarkerSet
nab_markersets.markersets   DecisionStore, MarkerSet, variable_names
```

The package root binds no names, so importing `nab_markersets` pulls in
no submodules.

`pickle.dumps` can write a `MarkerSet`, but `pickle.loads` fails because
direct construction is refused. `==` compares construction trees; use
`equivalent` to compare the environments two sets select.
