Skip to content

feu.compat

Registry-based package/Python-version compatibility resolution: given a package name and a target environment, find out which versions of that package are known to work.

Concepts

  • Target identifies the environment a constraint applies to: python_version and free_threaded (always concrete), plus optional os/arch. None on os/arch means "any" when stored in the registry, and "unspecified" when used as a lookup key.
  • VersionRange is one contiguous (min, max) span of valid package versions; either bound may be None for unbounded. A package/target can have several disjoint ranges (e.g. a package supported 1.0-1.10, then unsupported for a stretch, then supported again from 2.8 onward).
  • CompatRegistry stores package constraints populated by register_defaults() (the built-in DEFAULT_COMPAT table), discovery, and user calls to register_compat().

A lookup target matches a stored entry when python_version and free_threaded are equal, and the stored entry's os/arch are either None (wildcard) or equal to the lookup target's. When several entries match, the most specific one (most non-None os/arch) wins.

Discovery

discover_compat_targets(pkg_name, targets=DEFAULT_TARGETS) computes compatibility data from PyPI rather than requiring it to be hand-maintained. For each release, it parses the actual wheel filenames (via WheelTags / parse_wheel_filename) and requires_python metadata to determine, per target (Python version, OS, arch, free-threaded), the range of package versions that support it.

It is available as a library function for callers who need per-package, per-platform precision. It also powers the automatically discovered compatibility data under feu.compat.discovered (see feu.compat.defaults.DEFAULT_COMPAT for the human-curated counterpart, which takes precedence when both specify a given package/target): these modules are regenerated by dev/generate_discovered_compat.py, run on a schedule by the update-discovered-compat CI workflow (.github/workflows/update-discovered-compat.yaml).

Usage

>>> from feu.compat import Target, find_closest_version, is_valid_version
>>> target = Target(python_version="3.11")
>>> is_valid_version("numpy", "1.23.2", target)
True
>>> find_closest_version("numpy", "0.1.0", target)
'...'

Corrections can be registered on top of the built-in defaults:

>>> from feu.compat import Target, register_compat
>>> from feu.compat.registry import VersionRange
>>> register_compat({"mypkg": {Target(python_version="3.12"): [VersionRange("2.0", None)]}})

API reference

feu.compat

Contain a registry-based system for package/target compatibility resolution.

feu.compat.BaseCompatDiscoverer

Bases: ABC

Define the base class for package compatibility target discoverers.

Example
>>> from feu.compat.discoverers import CompatDiscoverer
>>> from feu.compat.target import Target
>>> discoverer = CompatDiscoverer()
>>> compat = discoverer.discover(
...     "numpy", targets=(Target(python_version="3.11", os="linux", arch="x86_64"),)
... )  # doctest: +SKIP

feu.compat.BaseCompatDiscoverer.discover abstractmethod

discover(
    pkg_name: str, targets: Sequence[Target]
) -> dict[Target, list[VersionRange]]

Discover the version range compatible with each target.

Parameters:

Name Type Description Default
pkg_name str

The package name to inspect (e.g., "numpy").

required
targets Sequence[Target]

The compatibility targets to compute constraints for. Each target must have concrete (non-None) os and arch.

required

Returns:

Type Description
dict[Target, list[VersionRange]]

A mapping of Target to a list of VersionRange, in the same shape expected by CompatRegistry.register_many.

feu.compat.CompatDiscoverer

Bases: BaseCompatDiscoverer

Implement the default compatibility target discoverer, using actual wheel filenames published on PyPI.

Unlike an approach that only inspects the requires_python metadata, this discoverer parses each release's wheel filenames to determine whether it shipped a build matching a target's free-threaded/OS/arch axes, not just its Python version. For pure-Python wheels (which carry no OS/arch information, and sometimes no Python-version information either), it falls back to the requires_python metadata.

Example
>>> from feu.compat.discoverers import CompatDiscoverer
>>> from feu.compat.target import Target
>>> discoverer = CompatDiscoverer()
>>> compat = discoverer.discover(
...     "numpy", targets=(Target(python_version="3.11", os="linux", arch="x86_64"),)
... )  # doctest: +SKIP

feu.compat.CompatDiscovererRegistry

Implement a registry that manages and dispatches compatibility discoverers based on package name.

Parameters:

Name Type Description Default
initial_state dict[str, BaseCompatDiscoverer] | None

Optional initial mapping of package name to discoverer. If provided, the state is copied to prevent external mutations.

None
Example
>>> from feu.compat.discoverers import CompatDiscovererRegistry, CompatDiscoverer
>>> registry = CompatDiscovererRegistry()
>>> registry.register("my_package", CompatDiscoverer())
>>> registry.has_discoverer("my_package")
True

feu.compat.CompatDiscovererRegistry.find_discoverer

find_discoverer(pkg_name: str) -> BaseCompatDiscoverer

Find the relevant compatibility discoverer for the given package.

Parameters:

Name Type Description Default
pkg_name str

The package name.

required

Returns:

Type Description
BaseCompatDiscoverer

The compatibility discoverer for the package, or a CompatDiscoverer if none is registered.

Example
>>> from feu.compat.discoverers import CompatDiscovererRegistry
>>> registry = CompatDiscovererRegistry()
>>> discoverer = registry.find_discoverer("pydantic")
>>> discoverer
CompatDiscoverer()

feu.compat.CompatDiscovererRegistry.has_discoverer

has_discoverer(pkg_name: str) -> bool

Indicate if a compatibility discoverer is registered for the given package name.

Parameters:

Name Type Description Default
pkg_name str

The package name.

required

Returns:

Type Description
bool

True if a discoverer is registered, otherwise False.

Example
>>> from feu.compat.discoverers import CompatDiscovererRegistry
>>> registry = CompatDiscovererRegistry()
>>> registry.has_discoverer("pydantic")
False

feu.compat.CompatDiscovererRegistry.register

register(
    pkg_name: str,
    discoverer: BaseCompatDiscoverer,
    exist_ok: bool = False,
) -> None

Register a compatibility discoverer for a given package.

Parameters:

Name Type Description Default
pkg_name str

The package name.

required
discoverer BaseCompatDiscoverer

The discoverer used for the given package.

required
exist_ok bool

If False, RuntimeError is raised if the package already exists. This parameter should be set to True to overwrite the discoverer for a package.

False

Raises:

Type Description
RuntimeError

if a discoverer is already registered for the package name and exist_ok=False.

Example
>>> from feu.compat.discoverers import CompatDiscovererRegistry, CompatDiscoverer
>>> registry = CompatDiscovererRegistry()
>>> registry.register("my_package", CompatDiscoverer())
>>> registry.has_discoverer("my_package")
True

feu.compat.CompatDiscovererRegistry.register_many

register_many(
    mapping: Mapping[str, BaseCompatDiscoverer],
    exist_ok: bool = False,
) -> None

Register multiple compatibility discoverers at once.

Parameters:

Name Type Description Default
mapping Mapping[str, BaseCompatDiscoverer]

Mapping of package name to discoverer.

required
exist_ok bool

If False, RuntimeError is raised if any package already exists. This parameter should be set to True to overwrite the discoverer for a package.

False

Raises:

Type Description
RuntimeError

if a discoverer is already registered for any of the package names and exist_ok=False.

Example
>>> from feu.compat.discoverers import CompatDiscovererRegistry, CompatDiscoverer
>>> registry = CompatDiscovererRegistry()
>>> registry.register_many({"my_package": CompatDiscoverer()})
>>> registry.has_discoverer("my_package")
True

feu.compat.CompatRegistry

Manage package version compatibility across different compatibility targets.

The registry maps package name to Target to a list of VersionRange. A package version is valid for a target if it falls within any of the registered ranges; an empty list means no version is valid for that target. A lookup target matches a stored entry when python_version and free_threaded are equal, and the stored entry's os/arch are either None (wildcard) or equal to the lookup target's os/arch. Among all matching entries, the most specific one (most non-None os/arch fields) wins; ties are broken by most-recently registered.

Parameters:

Name Type Description Default
initial_state dict[str, dict[Target, list[VersionRange]]] | None

Optional initial mapping of package constraints. If provided, the state is copied to prevent external mutations.

None
Example
>>> from feu.compat import CompatRegistry, Target
>>> from feu.compat.registry import VersionRange
>>> registry = CompatRegistry()
>>> registry.register(
...     pkg_name="numpy",
...     target=Target(python_version="3.11"),
...     ranges=[VersionRange("1.23.2", "2.4.6")],
... )
>>> registry.is_valid_version("numpy", "2.0.2", Target(python_version="3.11"))
True

feu.compat.CompatRegistry.state property

state: dict[str, dict[Target, list[VersionRange]]]

The registered package constraints.

feu.compat.CompatRegistry.find_closest_version

find_closest_version(
    pkg_name: str, pkg_version: str, target: Target
) -> str

Find the closest valid version for a package.

Parameters:

Name Type Description Default
pkg_name str

The package name to check (e.g., "numpy").

required
pkg_version str

The requested package version.

required
target Target

The compatibility target.

required

Returns:

Type Description
str

The closest valid version as a string.

Raises:

Type Description
UnsupportedVersionError

If no package version is valid for the given target.

feu.compat.CompatRegistry.get_config

get_config(
    pkg_name: str, target: Target
) -> list[VersionRange]

Get the list of valid version ranges for a package and compatibility target.

Parameters:

Name Type Description Default
pkg_name str

The package name to query (e.g., "numpy").

required
target Target

The compatibility target.

required

Returns:

Type Description
list[VersionRange]

The list of VersionRange for this target, or an empty

list[VersionRange]

list if no configuration matches.

feu.compat.CompatRegistry.get_version_ranges

get_version_ranges(
    pkg_name: str, target: Target
) -> list[tuple[Version | None, Version | None]]

Get the valid version ranges as Version objects.

Parameters:

Name Type Description Default
pkg_name str

The package name to query (e.g., "numpy").

required
target Target

The compatibility target.

required

Returns:

Type Description
list[tuple[Version | None, Version | None]]

A list of (min_version, max_version) tuples, either

list[tuple[Version | None, Version | None]]

value being None if unconstrained on that side.

Raises:

Type Description
UnsupportedVersionError

If no package version is valid for the given target.

feu.compat.CompatRegistry.is_unsupported

is_unsupported(pkg_name: str, target: Target) -> bool

Indicate if no package version is valid for a target.

This is distinct from a target having no registered configuration at all: an unconfigured target is treated as permissive (False), whereas a target explicitly registered with an empty range list is unsupported (True).

Parameters:

Name Type Description Default
pkg_name str

The package name to check (e.g., "numpy").

required
target Target

The compatibility target.

required

Returns:

Type Description
bool

True if the package has no valid version for the

bool

given target, False otherwise.

feu.compat.CompatRegistry.is_valid_version

is_valid_version(
    pkg_name: str, pkg_version: str, target: Target
) -> bool

Check if a package version is valid for a target.

Parameters:

Name Type Description Default
pkg_name str

The package name to check (e.g., "numpy").

required
pkg_version str

The package version to validate.

required
target Target

The compatibility target.

required

Returns:

Type Description
bool

True if valid for any registered range or

bool

unconfigured, False otherwise, including when no

bool

package version is valid for the given target.

feu.compat.CompatRegistry.register

register(
    pkg_name: str,
    target: Target,
    *,
    ranges: list[VersionRange],
    exist_ok: bool = False
) -> None

Register a package configuration for a compatibility target.

Parameters:

Name Type Description Default
pkg_name str

The package name to register (e.g., "numpy").

required
target Target

The compatibility target.

required
ranges list[VersionRange]

The list of valid version ranges for this target. An empty list means no version is valid.

required
exist_ok bool

If False, a RuntimeError is raised when a configuration already exists for this package and target. Set to True to overwrite.

False

Raises:

Type Description
RuntimeError

If a configuration already exists for the given package name and target, and exist_ok is False.

feu.compat.CompatRegistry.register_many

register_many(
    mapping: dict[str, dict[Target, list[VersionRange]]],
    exist_ok: bool = False,
) -> None

Register multiple package configurations at once.

Parameters:

Name Type Description Default
mapping dict[str, dict[Target, list[VersionRange]]]

Mapping of package name to Target to list of VersionRange.

required
exist_ok bool

Forwarded to register.

False

feu.compat.JaxCompatDiscoverer

Bases: BaseCompatDiscoverer

Implement a specialized compatibility discoverer for jax.

jax itself ships pure-Python wheels, so its own wheel filenames carry no OS/arch/Python-version information: the default CompatDiscoverer would (incorrectly) consider every jax release compatible with every target. In practice, jax requires jaxlib, whose wheels are platform-specific and are released in lockstep with matching jax version numbers. This discoverer therefore only considers a jax release compatible with a target if the jaxlib release with the same version number shipped a wheel matching that target's Python version/free-threaded/OS/arch axes.

Example
>>> from feu.compat.discoverers.jax import JaxCompatDiscoverer
>>> from feu.compat.target import Target
>>> discoverer = JaxCompatDiscoverer()
>>> compat = discoverer.discover(
...     "jax", targets=(Target(python_version="3.11", os="linux", arch="x86_64"),)
... )  # doctest: +SKIP

feu.compat.Target dataclass

Identify the environment a package compatibility constraint applies to.

Parameters:

Name Type Description Default
python_version str

The Python version, e.g. "3.11". Must be a "major.minor" string, without a free-threaded t suffix.

required
free_threaded bool

True for a free-threaded (no-GIL) Python build, e.g. 3.14t. Defaults to False.

False
os str | None

The operating system, e.g. "linux", "macos", "windows". None means "any OS" when used as a registry entry, and "unspecified" when used as a lookup target.

None
arch str | None

The CPU architecture, e.g. "x86_64", "arm64". None means "any architecture" when used as a registry entry, and "unspecified" when used as a lookup target.

None

Raises:

Type Description
ValueError

if python_version is not a "major.minor" string, or if os/arch is not one of the supported values.

Example
>>> from feu.compat.target import Target
>>> Target(python_version="3.14", free_threaded=True, os="linux", arch="x86_64")
Target(python_version='3.14', free_threaded=True, os='linux', arch='x86_64')

feu.compat.UnsupportedVersionError

Bases: Exception

Raised when no package version is compatible with a given target.

feu.compat.VersionRange

Bases: NamedTuple

Represent one contiguous range of valid package versions.

Parameters:

Name Type Description Default
min

The minimum valid package version, or None for no minimum.

required
max

The maximum valid package version, or None for no maximum.

required

feu.compat.WheelTags dataclass

Compatibility-relevant tags extracted from a wheel filename.

Parameters:

Name Type Description Default
python_version str | None

The CPython version, e.g. "3.14", or None for a pure-Python wheel compatible with any Python version. For an abi3 wheel, this is the minimum CPython version it supports, since the stable ABI makes it forward-compatible with later versions too.

required
free_threaded bool

True if the wheel targets a free-threaded (no-GIL) build.

required
os str | None

The operating system, e.g. "linux", "macos", "windows", or None for a pure-Python wheel compatible with any OS.

required
arch str | None

The CPU architecture, e.g. "x86_64", "arm64", or None for a pure-Python wheel compatible with any architecture.

required
abi3 bool

True if the wheel targets the CPython stable ABI (an abi3 ABI tag), meaning it is forward-compatible with every CPython version from python_version onward, not just that exact version.

False

feu.compat.discover_compat_targets

discover_compat_targets(
    pkg_name: str,
    targets: Sequence[Target] = DEFAULT_TARGETS,
) -> dict[Target, list[VersionRange]]

Discover the version range compatible with each target.

Uses the compatibility discoverer registered for pkg_name in the default global registry if one exists, otherwise falls back to the default CompatDiscoverer.

Parameters:

Name Type Description Default
pkg_name str

The package name to inspect (e.g., "numpy").

required
targets Sequence[Target]

The compatibility targets to compute constraints for. Each target must have concrete (non-None) os and arch. Defaults to DEFAULT_TARGETS.

DEFAULT_TARGETS

Returns:

Type Description
dict[Target, list[VersionRange]]

A mapping of Target to a list of VersionRange, in the same shape expected by CompatRegistry.register_many.

Example
>>> from feu.compat import discover_compat_targets
>>> compat = discover_compat_targets("numpy")  # doctest: +SKIP

feu.compat.find_closest_version

find_closest_version(
    pkg_name: str, pkg_version: str, target: Target
) -> str

Find the closest valid version for a package using the default registry.

Parameters:

Name Type Description Default
pkg_name str

The package name to check (e.g., "numpy").

required
pkg_version str

The requested package version.

required
target Target

The compatibility target.

required

Returns:

Type Description
str

The closest valid version as a string.

Example
>>> from feu.compat import find_closest_version, Target
>>> find_closest_version(
...     pkg_name="numpy", pkg_version="2.0.2", target=Target(python_version="3.11")
... )
'2.0.2'

feu.compat.get_default_registry

get_default_registry() -> CompatRegistry

Return the default global compatibility registry.

The registry is created on the first call and reused on all subsequent calls (singleton pattern).

Returns:

Type Description
CompatRegistry

A singleton CompatRegistry configured with the default

CompatRegistry

package version constraints.

Example
>>> from feu.compat import get_default_registry, Target
>>> registry = get_default_registry()
>>> registry.is_valid_version("numpy", "2.0.2", Target(python_version="3.11"))
True

feu.compat.is_valid_version

is_valid_version(
    pkg_name: str, pkg_version: str, target: Target
) -> bool

Check if a package version is valid for a target using the default registry.

Parameters:

Name Type Description Default
pkg_name str

The package name to check (e.g., "numpy").

required
pkg_version str

The package version to validate.

required
target Target

The compatibility target.

required

Returns:

Type Description
bool

True if valid or unconfigured, False otherwise.

Example
>>> from feu.compat import is_valid_version, Target
>>> is_valid_version(
...     pkg_name="numpy", pkg_version="2.0.2", target=Target(python_version="3.11")
... )
True

feu.compat.parse_wheel_filename

parse_wheel_filename(filename: str) -> list[WheelTags]

Parse a PEP 427 wheel filename into compatibility tags.

Parameters:

Name Type Description Default
filename str

The wheel filename, e.g. "numpy-2.3.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl".

required

Returns:

Type Description
list[WheelTags]

A list of WheelTags, one per Python-tag component (more than one only for a compressed pure-Python tag such as "py2.py3"), or an empty list if the filename doesn't end in .whl, targets a non-CPython/non-pure-Python interpreter, or its platform tag isn't in the known os/arch tables (and isn't the universal "any" platform). A bare major pure-Python component (e.g. "py3") yields python_version=None (compatible with any minor version), while a major.minor component (e.g. "py36") yields an exact version like a CPython tag. The universal "any" platform tag yields os=None and arch=None, meaning "compatible with any".

Example
>>> from feu.compat.wheel_tags import parse_wheel_filename
>>> parse_wheel_filename("numpy-2.3.0-cp312-cp312-macosx_11_0_arm64.whl")
[WheelTags(python_version='3.12', free_threaded=False, os='macos', arch='arm64', abi3=False)]

feu.compat.register_compat

register_compat(
    mapping: dict[str, dict[Target, list[VersionRange]]],
    exist_ok: bool = False,
) -> None

Register custom package configurations into the default global registry.

Parameters:

Name Type Description Default
mapping dict[str, dict[Target, list[VersionRange]]]

Mapping of package name to Target to a list of VersionRange.

required
exist_ok bool

If False (default), raises an error if any entry is already registered. If True, overwrites existing registrations silently.

False

Raises:

Type Description
RuntimeError

If any entry is already registered and exist_ok is False.

Example
>>> from feu.compat import register_compat, Target, VersionRange
>>> register_compat(
...     {"my_package": {Target(python_version="3.11"): [VersionRange("1.0.0", None)]}}
... )

feu.compat.resolve_target

resolve_target(
    python_version: str | None = None,
    free_threaded: bool | None = None,
    os: str | None = None,
    arch: str | None = None,
) -> Target

Resolve a Target from optional, possibly partial inputs.

If python_version ends with t, the target is a free-threaded build. In that case, free_threaded=False is invalid because it contradicts the t suffix. Any unspecified argument falls back to the current interpreter/environment value.

Parameters:

Name Type Description Default
python_version str | None

The Python version, e.g. "3.11" or "3.14t". If not provided, the current python version is used.

None
free_threaded bool | None

Whether the target is a free-threaded build. If not provided, it is inferred from python_version or the current interpreter's free-threaded status.

None
os str | None

The target OS. If not provided, the current OS is used.

None
arch str | None

The target CPU architecture. If not provided, the current architecture is used.

None

Returns:

Type Description
Target

The resolved target.

Raises:

Type Description
ValueError

if python_version ends with t and free_threaded=False is specified.

Example
>>> from feu.compat.target import resolve_target
>>> resolve_target(python_version="3.14t", os="linux", arch="x86_64")
Target(python_version='3.14', free_threaded=True, os='linux', arch='x86_64')

feu.compat.show_compat_targets

show_compat_targets(
    compat: dict[Target, list[VersionRange]],
    pkg_name: str | None = None,
) -> None

Print the output of discover_compat_targets as a table.

Parameters:

Name Type Description Default
compat dict[Target, list[VersionRange]]

The mapping of Target to a list of VersionRange, as returned by discover_compat_targets.

required
pkg_name str | None

The package name to show in the table title, if any.

None

Raises:

Type Description
RuntimeError

if the rich package is not installed.

Example
>>> from feu.compat import discover_compat_targets, show_compat_targets
>>> compat = discover_compat_targets("numpy")  # doctest: +SKIP
>>> show_compat_targets(compat, pkg_name="numpy")  # doctest: +SKIP