However, uv is _not_ intended to be an _exact_ clone of `pip`, and the further you stray from
common `pip` workflows, the more likely you are to encounter differences in behavior. In some cases,
those differences may be known and intentional; in others, they may be the result of implementation
details; and in others, they may be bugs.
This document outlines the known differences between uv and `pip`, along with rationale,
workarounds, and a statement of intent for compatibility in the future.
## Configuration files and environment variables
uv does not read configuration files or environment variables that are specific to `pip`, like
`pip.conf` or `PIP_INDEX_URL`.
Reading configuration files and environment variables intended for other tools has a number of
drawbacks:
1. It requires bug-for-bug compatibility with the target tool, since users end up relying on bugs in
the format, the parser, etc.
2. If the target tool _changes_ the format in some way, uv is then locked-in to changing it in
equivalent ways.
3. If that configuration is versioned in some way, uv would need to know _which version_ of the
target tool the user is expecting to use.
4. It prevents uv from introducing any settings or configuration that don't exist in the target
tool, since otherwise `pip.conf` (or similar) would no longer be usable with `pip`.
5. It can lead user confusion, since uv would be reading settings that don't actually affect its
behavior, and many users may _not_ expect uv to read configuration files intended for other
tools.
Instead, uv supports its own environment variables, like `UV_INDEX_URL`. In the future, uv will
also support persistent configuration in its own configuration file format (e.g., `pyproject.toml`
or `uv.toml` or similar). For more, see [#651](https://github.com/astral-sh/uv/issues/651).
## Transitive direct URL dependencies
While uv does support direct URL dependencies (e.g., `black @ https://...`), it does not support
nested (or "transitive") direct URL dependencies, instead requiring that any direct URL dependencies
are declared upfront.
For example, if `black @ https://...` itself had a dependency on `toml @ https://...`, uv would
reject the transitive direct URL dependency on `toml` and require that `toml` be declared as a
dependency in the `pyproject.toml` file, like:
```toml
# pyproject.toml
dependencies=[
"black @ https://...",
"toml @ https://...",
]
```
This is a deliberate choice to avoid the correctness and security issues associated with allowing
transitive dependencies to introduce arbitrary URLs into the dependency graph.
For example:
- Your package depends on `package_a==1.0.0`.
- Your package depends on `package_b==1.0.0`.
-`package_b==1.0.0` depends on `package_a @ https://...`.
If `package_a @ https://...` happens to resolve to version `1.0.0`, `pip` would install `package_a`
from the direct URL. This is a security issue, since the direct URL could be controlled by an
attacker, and a correctness issue, since the direct URL could resolve to an entirely different
package with the same name and version.
In the future, uv may allow transitive URL dependencies in some form (e.g., with user opt-in).
For more, see [#1808](https://github.com/astral-sh/uv/issues/1808).
## Pre-release compatibility
By default, uv will accept pre-release versions during dependency resolution in two cases:
1. If the package is a direct dependency, and its version markers include a pre-release specifier
(e.g., `flask>=2.0.0rc1`).
1. If _all_ published versions of a package are pre-releases.
If dependency resolution fails due to a transitive pre-release, uv will prompt the user to
re-run with `--prerelease=allow`, to allow pre-releases for all dependencies.
Alternatively, you can add the transitive dependency to your `requirements.in` file with
pre-release specifier (e.g., `flask>=2.0.0rc1`) to opt in to pre-release support for that specific
dependency.
In sum, uv needs to know upfront whether the resolver should accept pre-releases for a given
package. `pip`, meanwhile, _may_ respect pre-release identifiers in transitive dependencies
depending on the order in which the resolver encounters the relevant specifiers ([#1641](https://github.com/astral-sh/uv/issues/1641#issuecomment-1981402429)).
Pre-releases are [notoriously difficult](https://pubgrub-rs-guide.netlify.app/limitations/prerelease_versions)
to model, and are a frequent source of bugs in packaging tools. Even `pip`, which is viewed as a
reference implementation, has a number of open questions around pre-release handling ([#12469](https://github.com/pypa/pip/issues/12469),