# Resolution ## Resolution strategy By default, uv follows the standard Python dependency resolution strategy of preferring the latest compatible version of each package. For example, `uv pip install flask>=2.0.0` will install the latest version of Flask (at time of writing: `3.0.0`). However, uv's resolution strategy can be configured to support alternative workflows. With `--resolution=lowest`, uv will install the **lowest** compatible versions for all dependencies, both **direct** and **transitive**. Alternatively, `--resolution=lowest-direct` will opt for the **lowest** compatible versions for all **direct** dependencies, while using the **latest** compatible versions for all **transitive** dependencies. This distinction can be particularly useful for library authors who wish to test against the lowest supported versions of direct dependencies without restricting the versions of transitive dependencies. For example, given the following `requirements.in` file: ```text flask>=2.0.0 ``` Running `uv pip compile requirements.in` would produce the following `requirements.txt` file: ```text # This file was autogenerated by uv via the following command: # uv pip compile requirements.in blinker==1.7.0 # via flask click==8.1.7 # via flask flask==3.0.0 itsdangerous==2.1.2 # via flask jinja2==3.1.2 # via flask markupsafe==2.1.3 # via # jinja2 # werkzeug werkzeug==3.0.1 # via flask ``` However, `uv pip compile --resolution=lowest requirements.in` would instead produce: ```text # This file was autogenerated by uv via the following command: # uv pip compile requirements.in --resolution=lowest click==7.1.2 # via flask flask==2.0.0 itsdangerous==2.0.0 # via flask jinja2==3.0.0 # via flask markupsafe==2.0.0 # via jinja2 werkzeug==2.0.0 # via flask ``` ## Pre-release handling 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 a pre-release specifier (e.g., `flask>=2.0.0rc1`) to opt in to pre-release support for that specific dependency. Pre-releases are [notoriously difficult](https://pubgrub-rs-guide.netlify.app/limitations/prerelease_versions) to model, and are a frequent source of bugs in other packaging tools. uv's pre-release handling is _intentionally_ limited and _intentionally_ requires user opt-in for pre-releases, to ensure correctness. For more, see ["Pre-release compatibility"](./PIP_COMPATIBILITY.md#pre-release-compatibility) ## Dependency overrides Historically, `pip` has supported "constraints" (`-c constraints.txt`), which allows users to narrow the set of acceptable versions for a given package. uv supports constraints, but also takes this concept further by allowing users to _override_ the acceptable versions of a package across the dependency tree via overrides (`--override overrides.txt`). In short, overrides allow the user to lie to the resolver by overriding the declared dependencies of a package. Overrides are a useful last resort for cases in which the user knows that a dependency is compatible with a newer version of a package than the package declares, but the package has not yet been updated to declare that compatibility. For example, if a transitive dependency declares `pydantic>=1.0,<2.0`, but the user knows that the package is compatible with `pydantic>=2.0`, the user can override the declared dependency with `pydantic>=2.0,<3` to allow the resolver to continue. While constraints are purely _additive_, and thus cannot _expand_ the set of acceptable versions for a package, overrides _can_ expand the set of acceptable versions for a package, providing an escape hatch for erroneous upper version bounds. ## Multi-platform resolution By default, uv's `pip-compile` command produces a resolution that's known to be compatible with the current platform and Python version. Unlike Poetry and PDM, uv does not yet produce a machine-agnostic lockfile ([#2679](https://github.com/astral-sh/uv/issues/2679)). However, uv _does_ support resolving for alternate platforms and Python versions via the `--python-platform` and `--python-version` command line arguments. For example, if you're running uv on macOS, but want to resolve for Linux, you can run `uv pip compile --python-platform=linux requirements.in` to produce a `manylinux2014`-compatible resolution. Similarly, if you're running uv on Python 3.9, but want to resolve for Python 3.8, you can run `uv pip compile --python-version=3.8 requirements.in` to produce a Python 3.8-compatible resolution. The `--python-platform` and `--python-version` arguments can be combined to produce a resolution for a specific platform and Python version, enabling users to generate multiple lockfiles for different environments from a single machine. _N.B. Python's environment markers expose far more information about the current machine than can be expressed by a simple `--python-platform` argument. For example, the `platform_version` marker on macOS includes the time at which the kernel was built, which can (in theory) be encoded in package requirements. uv's resolver makes a best-effort attempt to generate a resolution that is compatible with any machine running on the target `--python-platform`, which should be sufficient for most use cases, but may lose fidelity for complex package and platform combinations._ ## Time-restricted reproducible resolutions uv supports an `--exclude-newer` option to limit resolution to distributions published before a specific date, allowing reproduction of installations regardless of new package releases. The date may be specified as an [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) timestamp (e.g., `2006-12-02T02:07:43Z`) or UTC date in the same format (e.g., `2006-12-02`). Note the package index must support the `upload-time` field as specified in [`PEP 700`](https://peps.python.org/pep-0700/). If the field is not present for a given distribution, the distribution will be treated as unavailable. To ensure reproducibility, messages for unsatisfiable resolutions will not mention that distributions were excluded due to the `--exclude-newer` flag — newer distributions will be treated as if they do not exist.