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¶
Targetidentifies the environment a constraint applies to:python_versionandfree_threaded(always concrete), plus optionalos/arch.Noneonos/archmeans "any" when stored in the registry, and "unspecified" when used as a lookup key.VersionRangeis one contiguous(min, max)span of valid package versions; either bound may beNonefor unbounded. A package/target can have several disjoint ranges (e.g. a package supported1.0-1.10, then unsupported for a stretch, then supported again from2.8onward).CompatRegistrystores package constraints populated from the automatically discovered data offeu.compat.discovered(loaded byget_default_registry()), and user calls toregister_compat(). A target registered with an empty list of ranges is explicitly unsupported, whereas a package/target with no entry is unconfigured and accepts any version.
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; ties are
broken by the most recently registered entry.
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. Packages whose wheels do not reflect their real
compatibility (e.g. duckdb, jax, polars, pydantic) use specialized
discoverers, see Discoverers. The discovered data
powers the built-in compatibility data under feu.compat.discovered: these
modules are regenerated by dev/generate_discovered_compat.py, run on a
schedule by the bot-update-discovered-compat CI workflow
(.github/workflows/bot-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 discovered data:
>>> 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., |
required |
targets
|
Sequence[Target]
|
The compatibility targets to compute constraints
for. Each target must have concrete (non- |
required |
Returns:
| Type | Description |
|---|---|
dict[Target, list[VersionRange]]
|
A mapping of |
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
|
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
|
|
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
|
Raises:
| Type | Description |
|---|---|
RuntimeError
|
if a discoverer is already registered for the
package name and |
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
|
Raises:
| Type | Description |
|---|---|
RuntimeError
|
if a discoverer is already registered for any
of the package names and |
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 deep-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, as a mapping of package
name to Target to a list of VersionRange.
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., |
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. The requested version is returned unchanged if it is valid or if the package is not configured for the target. Otherwise, the nearest range boundary is returned. |
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., |
required |
target
|
Target
|
The compatibility target. |
required |
Returns:
| Type | Description |
|---|---|
list[VersionRange]
|
The list of |
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., |
required |
target
|
Target
|
The compatibility target. |
required |
Returns:
| Type | Description |
|---|---|
list[tuple[Version | None, Version | None]]
|
A list of |
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., |
required |
target
|
Target
|
The compatibility target. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
bool
|
given target, |
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., |
required |
pkg_version
|
str
|
The package version to validate. |
required |
target
|
Target
|
The compatibility target. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
bool
|
unconfigured, |
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., |
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
|
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If a configuration already exists for the
given package name and target, and |
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 |
required |
exist_ok
|
bool
|
Forwarded to |
False
|
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If any configuration already exists for a
given package name and target, and |
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. |
required |
free_threaded
|
bool
|
|
False
|
os
|
str | None
|
The operating system, e.g. |
None
|
arch
|
str | None
|
The CPU architecture, e.g. |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
if |
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 |
required | |
max
|
The maximum valid package version, or |
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. |
required |
free_threaded
|
bool
|
|
required |
os
|
str | None
|
The operating system, e.g. |
required |
arch
|
str | None
|
The CPU architecture, e.g. |
required |
abi3
|
bool
|
|
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., |
required |
targets
|
Sequence[Target]
|
The compatibility targets to compute constraints for.
Each target must have concrete (non- |
DEFAULT_TARGETS
|
Returns:
| Type | Description |
|---|---|
dict[Target, list[VersionRange]]
|
A mapping of |
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., |
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. The requested version is returned unchanged if it is valid or if the package is not configured for the target. |
Raises:
| Type | Description |
|---|---|
UnsupportedVersionError
|
If no package version is valid for the given target. |
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
cached
¶
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). It is populated with the
automatically discovered constraints of feu.compat.discovered.
Returns:
| Type | Description |
|---|---|
CompatRegistry
|
A singleton |
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., |
required |
pkg_version
|
str
|
The package version to validate. |
required |
target
|
Target
|
The compatibility target. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
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.
|
required |
Returns:
| Type | Description |
|---|---|
list[WheelTags]
|
A list of |
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 |
required |
exist_ok
|
bool
|
If |
False
|
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If any entry is already registered and
|
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. |
None
|
free_threaded
|
bool | None
|
Whether the target is a free-threaded build.
If not provided, it is inferred from |
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 |
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 |
required |
pkg_name
|
str | None
|
The package name to show in the table title, if any. |
None
|
Raises:
| Type | Description |
|---|---|
RuntimeError
|
if the |
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