Features#

conda-pypi uses the conda plugin system to implement several features that make conda integrate better with the PyPI ecosystem:

The conda pypi subcommand#

This subcommand provides a safer way to install PyPI packages in conda environments by converting them to .conda format when possible. It offers two main subcommands that handle different aspects of PyPI integration.

conda pypi install#

The install command takes PyPI packages and converts them to the .conda format. Explicitly requested packages are always installed from PyPI and converted to .conda format to ensure you get exactly what you asked for. For dependencies, conda-pypi chooses the best source using a conda-first approach. If a dependency is available on conda channels, it will be installed with conda directly. If not available on conda channels, the dependency will be converted from PyPI to .conda format.

PyPI names are mapped to conda names with a bundled Grayskull table, plus a simple normalization rule when a package is not listed. conda pypi convert can load a replacement table from a JSON file via --name-mapping. With -e / --editable, a local project directory is built into a .conda package and installed.

You can preview what would be installed without making changes using --dry-run, install packages in editable development mode with --editable or -e, and force dependency resolution from PyPI without using conda channels using --ignore-channels.

conda pypi convert#

The convert command transforms PyPI packages to .conda format without installing them, which is useful for creating conda packages from PyPI distributions or preparing packages for offline installation. You can specify where to save the converted packages using -d, --dest, or --output-dir. The command supports converting multiple packages at once and can skip conda channel checks entirely with --ignore-channels to convert directly from PyPI.

Here are some common usage patterns:

# Convert packages to current directory
conda pypi convert httpx cowsay

# Convert to specific directory
conda pypi convert -d ./my_packages httpx cowsay

# Convert without checking conda channels first
conda pypi convert --ignore-channels some-pypi-only-package

# Convert with custom name mapping
conda pypi convert --name-mapping ./mapping.json ./my-package-1.0.0-py3-none-any.whl

PyPI-to-Conda Conversion Engine#

conda-pypi includes a powerful conversion engine that enables direct conversion of pure Python wheels to .conda packages with proper translation of Python package metadata to conda format. The system includes name mapping of PyPI dependencies to conda equivalents and provides cross-platform support for package conversion, ensuring that converted packages work across different operating systems and architectures.

The wheel’s SPDX-style License-Expression (or legacy License field) is copied into conda metadata (license in info/index.json and about.json). When the wheel lists files under PEP 639 License-File, those files are also copied into info/licenses/ in the .conda package (CEP 34). Resolution checks .dist-info/<path> (pre-PEP 639 wheels) and .dist-info/licenses/<path> (PEP 639, Metadata-Version 2.4+).

Dependency environment markers (PEP 508)#

PyPI environment markers are translated for the solver where possible. When building installable .conda packages from wheels, [when="…"] is not attached to dependency strings. The extra == "…" marker is split into per-extra tables, and other marker conditions are omitted from depends. See PEP 508 marker conversion.

Wheel channels#

Experimental

This feature is experimental. It is based on a draft CEP for Repodata Wheel Support that is still under active discussion and subject to change.

If you maintain a conda channel, you can now serve Python wheels directly alongside regular conda packages. Add your wheels to a v3.whl section in repodata.json and point each entry at the wheel URL. conda install will pick them up, resolve their dependencies, and extract them correctly, with no pre-conversion step required.

conda install -c https://my-wheel-channel requests

Wheels served this way behave like any other conda package.

Extras and markers#

Wheels in a channel can declare dependency specifier extras via an extra_depends field in the repodata entry.

In the PyPA grammar, extras are a comma-separated list of names. Multiple extras union their requirements, and there is no reserved name meaning “all extras.” Optional extras in extra_depends are resolved by the Rattler solver.

Editable Package Support#

conda-pypi supports editable (development) installs for local project directories: the project is built into a .conda package and installed into the environment. This is intended for workflows where you edit code in a checkout on disk.

Here are some common usage patterns for editable installations:

# Install local project in editable mode
conda pypi install -e ./my-project/

# Multiple local editable packages
conda pypi install -e ./package1/ -e ./package2/

conda env integrations#

Coming soon

environment.yml files famously allow a pip subsection in their dependencies. This is handled internally by conda env via a pip subprocess. We are adding new plugin hooks so conda-pypi can handle these in the same way we do with the conda pypi subcommand.

Environment marker files#

conda-pypi adds support for PEP-668’s EXTERNALLY-MANAGED environment marker files. These files tell pip and other PyPI installers not to install or remove any packages in that environment, guiding users towards safer alternatives.

When these marker files are present, they display a message letting users know that the conda pypi subcommand is available as a safer alternative. The primary goal is to avoid accidental overwrites that could break your conda environment. If you need to use pip directly, you can still do so by adding the --break-system-packages flag, though this is generally not recommended in conda environments.