🧩 Build System Integration¢

Tip

See example/ for working examples of using unidep with different build systems.

unidep seamlessly integrates with popular Python build systems to simplify dependency management in your projects.

Local Dependencies in MonoreposΒΆ

Local dependencies are essential for monorepos and multi-package projects, allowing you to:

  • Share code between packages during development

  • Maintain separate releases for each package

  • Test changes across multiple packages simultaneously

However, when building wheels for distribution, local paths create non-portable packages that only work on the original system.

PyPI Alternatives for Local DependenciesΒΆ

UniDep solves this problem by letting you specify both local paths (for development) and PyPI packages (for distribution):

# requirements.yaml
dependencies:
  - numpy
  - pandas

local_dependencies:
  # Standard string format for local dependencies
  - ../shared-lib

  # Dictionary format with optional PyPI alternative for build-time
  - local: ../auth-lib
    pypi: company-auth-lib>=1.0

  - local: ../utils
    pypi: company-utils~=2.0

Or in pyproject.toml:

[tool.unidep]
dependencies = ["numpy", "pandas"]

local_dependencies = [
    # Standard string format for local dependencies
    "../shared-lib",

    # Dictionary format with optional PyPI alternative for build-time
    {local = "../auth-lib", pypi = "company-auth-lib>=1.0"},
    {local = "../utils", pypi = "company-utils~=2.0"},
]

How it works:

  • During development (e.g., unidep install or pip install -e .): Uses local paths when they exist

  • When building wheels: PyPI alternatives (if specified) are used to create portable packages

  • The standard string format continues to work as always for local dependencies

Tip

PyPI alternatives ensure your wheels are portable and can be installed anywhere, not just on the build system.

Build System BehaviorΒΆ

Important differences between build backends:

  • Setuptools: Builds wheels containing file:// URLs with absolute paths. These wheels only work on the original system.

  • Hatchling: Rejects file:// URLs by default, preventing non-portable wheels.

To ensure portable wheels, you can use the UNIDEP_SKIP_LOCAL_DEPS environment variable:

# Force use of PyPI alternatives even when local paths exist
UNIDEP_SKIP_LOCAL_DEPS=1 python -m build

# For hatch projects
UNIDEP_SKIP_LOCAL_DEPS=1 hatch build

# For uv build
UNIDEP_SKIP_LOCAL_DEPS=1 uv build

Note

When UNIDEP_SKIP_LOCAL_DEPS=1 is set:

  • Local dependencies with PyPI alternatives β†’ use PyPI package

  • Local dependencies without PyPI alternatives β†’ skipped entirely

  • Dependencies from local packages are still included (from their requirements.yaml/pyproject.toml)

Example packagesΒΆ

Explore these installable example packages to understand how unidep integrates with different build tools and configurations:

Project

Build Tool

pyproject.toml

requirements.yaml

setup.py

setup_py_project

setuptools

βœ…

βœ…

βœ…

setuptools_project

setuptools

βœ…

βœ…

❌

pyproject_toml_project

setuptools

βœ…

❌

❌

hatch_project

hatch

βœ…

βœ…

❌

hatch2_project

hatch

βœ…

❌

❌

Setuptools IntegrationΒΆ

For projects using setuptools, configure unidep in pyproject.toml and either specify dependencies in a requirements.yaml file or include them in pyproject.toml too.

  • Using pyproject.toml only: The [project.dependencies] field in pyproject.toml gets automatically populated from requirements.yaml or from the [tool.unidep] section in pyproject.toml.

  • Using setup.py: The install_requires field in setup.py automatically reflects dependencies specified in requirements.yaml or pyproject.toml.

Example pyproject.toml Configuration:

[build-system]
build-backend = "setuptools.build_meta"
requires = ["setuptools", "unidep"]

[project]
dynamic = ["dependencies"]

Hatchling IntegrationΒΆ

For projects managed with Hatch, unidep can be configured in pyproject.toml to automatically process the dependencies from requirements.yaml or from the [tool.unidep] section in pyproject.toml.

Example Configuration for Hatch:

[build-system]
requires = ["hatchling", "unidep"]
build-backend = "hatchling.build"

[project]
dynamic = ["dependencies"]
# Additional project configurations

[tool.hatch.metadata.hooks.unidep]
# Enable the unidep plugin

[tool.hatch.metadata]
allow-direct-references = true

[tool.unidep]
# Your dependencies configuration