Skip to main content

A Python library for managing multiple versions of dependencies

Project description

🐦 pyvers

A Python library for dynamic dispatch based on module versions and backends.

What can you do with pyvers?

  • 🔄 Handle breaking changes between different versions of a library without cluttering your code
  • 🔀 Switch seamlessly between different backend implementations (e.g., CPU vs GPU)
  • ✨ Support multiple versions of a dependency in the same codebase without complex if/else logic
  • 🚀 Write version-specific optimizations while maintaining backward compatibility
  • 🧹 Keep your code clean and maintainable while supporting multiple environments

Usage

pyvers lets you write version-specific implementations that are automatically selected based on the installed package version or backend. Here's a simple example using the register API (recommended):

from pyvers import implement_for, register_backend, get_backend, set_backend

# Register numpy backend - you could register more than one backend!
register_backend(group="numpy", backends={"numpy": "numpy"})

# Define the function with @implement_for, then register version-specific implementations
@implement_for("numpy")
def create_mask(arr):
    """Create a boolean mask marking positive values."""
    raise NotImplementedError("No matching numpy version found")

# Function for NumPy < 2.0 (using bool8)
@create_mask.register(from_version=None, to_version="2.0.0")
def _(arr):
    np = get_backend("numpy")
    return np.array([x > 0 for x in arr], dtype=np.bool8)

# Function for NumPy >= 2.0 (using bool_)
@create_mask.register(from_version="2.0.0")
def _(arr):
    np = get_backend("numpy")
    return np.array([x > 0 for x in arr], dtype=np.bool_)

# The correct implementation is automatically chosen based on your NumPy version
result = create_mask([-1, 2, -3, 4])
print("NumPy result:", result)

The .register() API follows the same pattern as functools.singledispatch. Using _ as the function name is a Python convention that linters recognize, so you don't need # noqa comments.

Alternative: Traditional API

You can also use the traditional decorator pattern (requires # noqa: F811 for linters):

@implement_for("numpy", from_version=None, to_version="2.0.0")
def create_mask(arr):
    np = get_backend("numpy")
    return np.array([x > 0 for x in arr], dtype=np.bool8)

@implement_for("numpy", from_version="2.0.0")
def create_mask(arr):  # noqa: F811
    np = get_backend("numpy")
    return np.array([x > 0 for x in arr], dtype=np.bool_)

Check out the examples folder for more advanced use cases:

  • Switching between NumPy and JAX.numpy backends
  • Handling CPU (SciPy) vs GPU (CuPy) implementations
  • Managing breaking changes in PyTorch 2.0
  • Supporting both gym and gymnasium APIs

Installation

pip install pyvers

Features

Version-based dispatch

Automatically select the right implementation based on package versions:

@implement_for("torch")
def optimize_model(model):
    """Optimize a model using version-appropriate techniques."""
    raise NotImplementedError("No matching torch version")

@optimize_model.register(from_version="2.0.0")
def _(model):
    return torch.compile(model)  # Only available in PyTorch 2.0+

@optimize_model.register(from_version=None, to_version="2.0.0")
def _(model):
    return model  # Fallback for older versions

Backend switching

Easily switch between different implementations:

# Register both backends
register_backend(group="numpy", backends={
    "numpy": "numpy",
    "jax.numpy": "jax.numpy"
})

# Use context manager to switch backends
with set_backend("numpy", "jax.numpy"):
    result = your_function()  # Uses JAX
with set_backend("numpy", "numpy"):
    result = your_function()  # Uses NumPy

Dynamic imports

Backends are imported only when needed, so you can have optional dependencies:

register_backend(group="sparse", backends={
    "scipy.sparse": "scipy.sparse",        # CPU backend
    "cupyx.scipy.sparse": "cupyx.scipy.sparse"  # GPU backend - does NOT require cupy to be installed!
})

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Development

Setup

  1. Clone the repository
  2. Install Poetry (package manager)
  3. Install dependencies:
    poetry install
    

Running Tests

poetry run pytest

This will run the test suite with coverage reporting.

Code Quality

We use Ruff for linting and code formatting. Ruff combines multiple Python linters into a single fast, unified tool.

To check your code:

poetry run ruff check .

To automatically fix issues:

poetry run ruff check --fix .

Ruff is configured to:

  • Follow PEP 8 style guide
  • Sort imports automatically
  • Check for common bugs and code complexity
  • Target Python 3.12+

See pyproject.toml for the complete linting configuration.

License

This project is licensed under the MIT License - see the LICENSE file for details.

## Citation

pyvers was developped as part of TorchRL.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyvers-0.2.1.tar.gz (12.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyvers-0.2.1-py3-none-any.whl (11.6 kB view details)

Uploaded Python 3

File details

Details for the file pyvers-0.2.1.tar.gz.

File metadata

  • Download URL: pyvers-0.2.1.tar.gz
  • Upload date:
  • Size: 12.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pyvers-0.2.1.tar.gz
Algorithm Hash digest
SHA256 35afa23a6851acb9a669c2c79e00667a6dee478732d06ce5aea31aa87c856c47
MD5 d6be75426351338905b1eb8cb8a673c8
BLAKE2b-256 2090cef7399edb1f31b6bd624d27d5d9a5ad0610bdb462e2b52d776b7798d1bb

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyvers-0.2.1.tar.gz:

Publisher: release.yml on vmoens/pyvers

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyvers-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: pyvers-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 11.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pyvers-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 dc782e94dd32564e15df3e1ce28cef173b084992572d3c5d5103c4df69fd3a68
MD5 86629a0a5b685c60b77259887b81a9cf
BLAKE2b-256 90b74447c56479efd1a69dca25cf00b69c999f0ddad4de6d43c1ab4d95a7406d

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyvers-0.2.1-py3-none-any.whl:

Publisher: release.yml on vmoens/pyvers

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page