Commit Graph

66 Commits

Author SHA1 Message Date
Zanie Blue d0a6f5d13f
Add support for relative durations in `exclude-newer` (#16814)
Adds support for "friendly" durations like, 1 week, 7 days, 24 hours
using Jiff's parser. During resolution, we calculate this relative to
the current time and resolve it into a concrete timestamp for the
lockfile. If the span has not changed, e.g., to another relative value,
then locking again will not change the lockfile. The locked timestamp
will only be updated when the lockfile is invalidated, e.g., with
`--upgrade`. This prevents the lockfile from repeatedly churning when a
relative value is used.
2025-12-09 19:52:14 +00:00
Tom Schafer fd7e6d0a05
Add SBOM export support (#16523)
Co-authored-by: Will Rollason <william.rollason@snyk.io>
2025-11-20 12:52:31 -05:00
Zanie Blue 11fe8f70f9
Add `exclude-newer-package` (#14489)
Adds `exclude-newer-package = { package = timestamp, ... } ` and
`--exclude-newer-package package=timestamp`. These take precedence over
`exclude-newer` for a given package.

This does need to be serialized to the lockfile, so the revision is
bumped to 3. I tested a previous version and we can read a lockfile with
this information just fine.

Closes https://github.com/astral-sh/uv/issues/14394
2025-07-29 17:00:25 -05:00
Simon Sure 8afbd86f03
make `ErrorTree` for `NoSolutionError` externally accessible (#14444)
Hey, are you okay with exposing the `ErrorTree` for library consumers?

We have a use case that needs more information on conflicts. We need the
tree-structure of the conflict and be able to traverse it in particular.

Signed-off-by: Simon Sure <ssure@palantir.com>
2025-07-03 11:43:59 -05:00
Aria Desires 5021840919
Add `[tool.uv.dependency-groups].mygroup.requires-python` (#13735)
This allows you to specify requires-python on individual dependency-groups,
with the intended usecase being "oh my dev-dependencies have a higher
requires-python than my actual project".

This includes a large driveby move of the RequiresPython type to
uv-distribution-types to allow us to generate the appropriate markers at
this point in the code. It also migrates RequiresPython from
pubgrub::Range to version_ranges::Ranges, and makes several pub(crate)
items pub, as it's no longer defined in uv_resolver.

Fixes #11606
2025-06-13 22:04:13 +00:00
Charlie Marsh dc5b3762f3
Show tag hints when failing to find a compatible wheel in `pylock.toml` (#13136)
## Summary

Closes #13135.
2025-04-27 12:56:50 -04:00
Charlie Marsh 2ba4edfbbe
Add PEP 751 support to `uv pip compile` (#13019)
## Summary

You now specify `--format pylock.toml` or `-o pylock.toml` to output in
PEP 751 format.
2025-04-21 22:48:54 +00:00
Charlie Marsh d8cea2fd49
Add `uv export` support for PEP 751 (#12955)
## Summary

This PR adds `uv export` support for [PEP
751](https://peps.python.org/pep-0751). We don't yet expose a way to
consume the generated lockfile, but it's a first step.

The logic to go from `uv.lock` to "flat set of packages to include, with
markers telling us when to include them" is all shared with the
`requirements.txt` export (and extracted in
https://github.com/astral-sh/uv/pull/12956). So most of the code is just
converting from our internal types to the PEP 751 schema.
2025-04-21 21:21:17 +00:00
Charlie Marsh b2dac9979d
Use Hashbrown's raw entry API to reduce hashes and clone in priority (#10881)
## Summary

I'm open to not merging this -- I was kind of just interested in what
the API looked like. But the idea is: we can avoid hashing values twice
and unnecessarily cloning within the priority map by using the raw entry
API.
2025-01-23 09:34:37 -05:00
Charlie Marsh 7c47a457d9
Move installable targets out of `uv-resolver` crate (#10126)
## Summary

The proximate motivation is that I want to add new variant for scripts,
but `uv-resolver` can't depend on `uv-scripts` without creating a
circular dependency. However, I think this _does_ just make more sense
-- the resolver crate shouldn't be coupled to the various kinds of
workspaces, and these details are mostly encoded in `projects/lock.rs`
and similar files.
2024-12-24 19:01:50 -05:00
Charlie Marsh b2459e6326
Introduce a `--fork-strategy` preference mode (#9868)
## Summary

This PR makes the behavior in https://github.com/astral-sh/uv/pull/9827
the default: we try to select the latest supported package version for
each supported Python version, but we still optimize for choosing fewer
versions when stratifying by platform.

However, you can opt out with `--fork-strategy fewest`.

Closes https://github.com/astral-sh/uv/issues/7190.
2024-12-13 16:05:07 -05:00
Andrew Gallant edf875e306
add conflict markers to the lock file (#9370)
This PR adds a notion of "conflict markers" to the lock file as an
attempt to address #9289. The idea is to encode a new kind of boolean
expression indicating how to choose dependencies based on which extras
are activated.

As an example of what conflict markers look like, consider one of the
cases
brought up in #9289, where `anyio` had unconditional dependencies on
two different versions of `idna`. Now, those are gated by markers, like
this:

```toml
        [[package]]
        name = "anyio"
        version = "4.3.0"
        source = { registry = "https://pypi.org/simple" }
        dependencies = [
            { name = "idna", version = "3.5", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-7-project-foo'" },
            { name = "idna", version = "3.6", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-7-project-bar' or extra != 'extra-7-project-foo'" },
            { name = "sniffio" },
        ]
```

The odd extra values like `extra-7-project-foo` are an encoding of not
just the conflicting extra (`foo`) but also the package it's declared
for (`project`). We need both bits of information because different
packages may have the same extra name, even if they are completely
unrelated. The `extra-` part is a prefix to distinguish it from groups
(which, in this case, would be encoded as `group-7-project-foo` if `foo`
were a dependency group). And the `7` part indicates the length of the
package name which makes it possible to parse out the package and extra
name from this encoding. (We don't actually utilize that property, but
it seems like good sense to do it in case we do need to extra
information from these markers.)

While this preserves PEP 508 compatibility at a surface level, it does
require utilizing this encoding scheme in order
to evaluate them when they're present (which only occurs when
conflicting extras/groups are declared).

My sense is that the most complex part of this change is not just adding
conflict markers, but their simplification. I tried to address this in
the code comments and commit messages.

Reviewers should look at this commit-by-commit.

Fixes #9289, Fixes #9546, Fixes #9640, Fixes #9622, Fixes #9498, Fixes
#9701, Fixes #9734
2024-12-10 10:57:22 -05:00
Andrew Gallant dae584d49b uv-resolver: introduce new UniversalMarker type
This effectively combines a PEP 508 marker and an as-yet-specified
marker for expressing conflicts among extras and groups.

This just defines the type and threads it through most of the various
points in the code that previously used `MarkerTree` only. Some parts
do still continue to use `MarkerTree` specifically, e.g., when dealing
with non-universal resolution or exporting to `requirements.txt`.

This doesn't change any behavior.
2024-11-22 08:21:23 -05:00
Charlie Marsh 821f3de095
Automatically retry body errors when processing response (#9213)
## Summary

The reqwest middleware doesn't retry errors that occur "after" the
request completes -- but in some cases, these do include spurious errors
that we want to retry. See https://github.com/astral-sh/uv/issues/8144
for examples. This PR adds a second retry layer during the response
_handler_, which should help with some of the spurious failures we see
in the linked issue.

Closes https://github.com/astral-sh/uv/issues/8144.
2024-11-19 04:14:58 +00:00
Charlie Marsh 8dd095cab8
Include version constraints in derivation chains (#9112)
## Summary

Derivation chains can now include the versions at which a package was
requested.
2024-11-15 15:06:24 -05:00
Charlie Marsh fe477c3417
Show full derivation chain when encountering build failures (#9108)
## Summary

This PR adds context to our error messages to explain _why_ a given
package was included, if we fail to download or build it.

It's quite a large change, but it motivated some good refactors and
improvements along the way.

Closes https://github.com/astral-sh/uv/issues/8962.
2024-11-14 15:48:26 -05:00
Charlie Marsh b37170df94
Rename `ResolutionGraph` to `ResolverOutput` (#9103)
## Summary

As discussed in Discord... This struct has evolved to include a lot of
information apart from the `petgraph::Graph`. And I want to add a graph
to the simplified `Resolution` type. So I think this name makes more
sense.
2024-11-14 14:51:11 +00:00
Andrew Gallant 06943ca870 uv-pypi-types: make room for group names in addition to extras
This adds support for providing conflicting group names in addition to
extra names to `Conflicts`.

This merely makes "room" for it in the types while keeping everything
working. We'll add proper support for it in the next commit.

Note that one interesting trick we do here is depend directly on
`hashbrown` so that we can make use of its `Equivalent` trait. This in
turn lets us use things like `ConflictItemRef` as a lookup key for a
hashset that contains `ConflictItem`. This mirrors using a `&str` as a
lookup key for a hashset that contains `String`, but works for arbitrary
types. `std` doesn't support this, but `hashbrown` does. This trick in
turn lets us simplify some of our data structures.

This also rejiggers some of the serde-interaction with the conflicting
types. We now use a wire type to represent our conflicting items for
more flexibility. i.e., Support `extra` XOR `group` fields.
2024-11-14 08:02:46 -05:00
Charlie Marsh 29e1b15473
Add `uv tree --outdated` (#8893)
## Summary

Similar to `pip list --outdated`, but for `uv tree`.

## Test Plan

Looks like:

```
foo v0.1.0
└── flask v2.0.0 (latest: v3.0.3)
    ├── click v8.1.7
    ├── itsdangerous v2.2.0
    ├── jinja2 v3.1.4
    │   └── markupsafe v3.0.2
    └── werkzeug v3.1.2
        └── markupsafe v3.0.2
```

With `(latest: v3.0.3)` in bold cyan.
2024-11-07 14:10:46 -06:00
Andrew Gallant acaed763b7 uv: use ResolverEnvironment instead of ResolverMarkers
This updates the surrounding code to use the new ResolverEnvironment
type. In some cases, this simplifies caller code by removing case
analysis. There *shouldn't* be any behavior changes here. Some test
snapshots were updated to account for some minor tweaks to error
messages.

I didn't split this up into separate commits because it would have been
too difficult/costly.
2024-11-04 11:09:06 -05:00
Charlie Marsh d3e50a2376
Enable `--all-packages --frozen` in `uv sync` and `uv export` (#8760)
## Summary

This PR improves the interaction of `--frozen` such that we reduce the
dependency on the `pyproject.toml` and increase the dependency on the
`uv.lock`. Specifically, we now read the list of workspace members from
the `uv.lock` rather than the `pyproject.toml`, which means we don't
need to discover the member `pyproject.toml` files in order to perform a
`uv sync --frozen --all-packages`.
2024-11-02 02:48:55 +00:00
konsti c1a0fb35e8
Simplify pep440 -> version ranges conversion (#8683) 2024-10-30 13:10:48 +01:00
konsti e5b8cdba70
Merge uv-pubgrub into uv-pep440 (#8669) 2024-10-29 20:15:18 +01:00
Charlie Marsh 2651aee33f
Enforce lockfile schema versions (#8509)
## Summary

Historically, we haven't enforced schema versions. This PR adds a
versioning policy such that, if a uv version writes schema v2, then...

- It will always reject lockfiles with schema v3 or later.
- It _may_ reject lockfiles with schema v1, but can also choose to read
them, if possible.

(For example, the change we proposed to rename `dev-dependencies` to
`dependency-groups` would've been backwards-compatible: newer versions
of uv could still read lockfiles that used the `dev-dependencies` field
name, but older versions should reject lockfiles that use the
`dependency-groups` field name.)

Closes https://github.com/astral-sh/uv/issues/8465.
2024-10-24 12:23:56 -04:00
Charlie Marsh 9a76e47888
Allow multiple pinned indexes in `tool.uv.sources` (#7769)
## Summary

This PR lifts the restriction that a package must come from a single
index. For example, you can now do:

```toml
[project]
name = "project"
version = "0.1.0"
readme = "README.md"
requires-python = ">=3.12"
dependencies = ["jinja2"]

[tool.uv.sources]
jinja2 = [
    { index = "torch-cu118", marker = "sys_platform == 'darwin'"},
    { index = "torch-cu124", marker = "sys_platform != 'darwin'"},
]

[[tool.uv.index]]
name = "torch-cu118"
url = "https://download.pytorch.org/whl/cu118"

[[tool.uv.index]]
name = "torch-cu124"
url = "https://download.pytorch.org/whl/cu124"
```

The construction is very similar to the way we handle URLs today: you
can have multiple URLs for a given package, but they must appear in
disjoint forks. So most of the code is just adding that abstraction to
the resolver, following our handling of URLs.

Closes #7761.
2024-10-15 22:58:15 +00:00
Charlie Marsh c683191408
Don't recommend `--prerelease=allow` for source dist builds (#8192)
## Summary

Closes https://github.com/astral-sh/uv/issues/3686.
2024-10-14 21:04:30 -04:00
Tim de Jager 50116efb10
expose `FlatDistributions` struct in public API (#7833)
Would it be okay to expose this struct? We currently use our own
ResolveProvider, and it would be nice to use the `FlatDistributions` for
easy `VersionMap` creation.

Thanks!
2024-10-01 07:46:32 -05:00
Andrew Gallant 83f1abdf57 uv-resolver: add error checking for conflicting distributions
This PR adds some additional sanity checking on resolution graphs to
ensure we can never install different versions of the same package into
the same environment.

I used code similar to this to provoke bugs in the resolver before the
release, but it never made it into `main`. Here, we add the error
checking to the creation of `ResolutionGraph`, since this is where it's
most convenient to access the "full" markers of each distribution.

We only report an error when `debug_assertions` are enabled to avoid
rendering `uv` *completely* unusuable if a bug were to occur in a
production binary. For example, maybe a conflict is detected in a marker
environment that isn't actually used. While not ideal, `uv` is still
usable for any other marker environment.

Closes #5598
2024-09-24 10:55:23 -04:00
Charlie Marsh 1ccc15e7bb
Use correct ordering semantics for narrowing upper-bounded Python requirements (#7031)
## Summary

We need to use different ordering semantics for upper and lower Python
bounds.

Closes https://github.com/astral-sh/uv/issues/6911.
2024-09-04 15:57:14 +00:00
Charlie Marsh 34d74501ac
Respect the user's upper-bound in `requires-python` (#6824)
## Summary

We now respect the user-provided upper-bound in for `requires-python`.
So, if the user has `requires-python = "==3.11.*"`, we won't explore
forks that have `python_version >= '3.12'`, for example.

However, we continue to _only_ compare the lower bounds when assessing
whether a dependency is compatible with a given Python range.

Closes https://github.com/astral-sh/uv/issues/6150.
2024-08-29 18:37:05 +00:00
Charlie Marsh cbfc928a9c
Add `uv export --format requirements.txt` (#6778)
## Summary

The interface here is intentionally a bit more limited than `uv pip
compile`, because we don't want `requirements.txt` to be a system of
record -- it's just an export format. So, we don't write annotation
comments (i.e., which dependency is requested from which), we don't
allow writing extras, etc. It's just a flat list of requirements, with
their markers and hashes.

Closes #6007.

Closes #6668.

Closes #6670.
2024-08-29 17:46:42 +00:00
Charlie Marsh 9d514cbbe0
Return a structured result from `Lock::satisfies` (#6119)
## Summary

Gives the caller control over how messages are reported back to the
user. Also merges the index-location validation into the lock, since
we're already iterating over the packages.
2024-08-15 13:19:40 -04:00
Charlie Marsh e3f345ce09
Validate lockfile (rather than re-resolve) in `uv lock` (#6091)
## Summary

Historically, in order to "resolve from a lockfile", we've taken the
lockfile, used it to pre-populate the in-memory metadata index, then run
a resolution. If the resolution didn't match our existing resolution, we
re-resolved from scratch.

This was an appealing approach because (in theory) it didn't require any
dedicated logic beyond pre-populating the index. However, it's proven to
be _really_ hard to get right, because it's a stricter requirement than
we need. We just need the current lockfile to _satisfy_ the requirements
provided by the user. We don't actually need a second resolution to
produce the exact same result. And it's not uncommon that this second
resolution differs, because we seed it with preferences, which
fundamentally changes its course. We've worked hard to minimize those
"instabilities", but they're still present.

The approach here is intended to be much simpler. Instead of resolving
from the lockfile, we just check if the current resolution satisfies the
state of the workspace. Specifically, we check if the lockfile (1)
contains all the relevant members, and (2) matches the metadata for all
dependencies, recursively. (We skip registry dependencies, assuming that
they're immutable.)

This may actually be too conservative, since we can have resolutions
that satisfy the requirements, even if the requirements have changed
slightly. But we want to bias towards correctness for now.

My hope is that this scheme will be more performant, simpler, and more
robust.

Closes https://github.com/astral-sh/uv/issues/6063.
2024-08-14 20:00:15 -04:00
Charlie Marsh 2822dde8cb
Add resolver error context to `run` and `tool run` (#5991)
## Summary

Closes https://github.com/astral-sh/uv/issues/5530.
2024-08-10 03:21:56 +00:00
Charlie Marsh a9a535da14
Use lockfile directly in `uv tree` (#5761)
## Summary

Ensures that we properly handle (1) duplicated packages and (2) packages
that aren't relevant to the current platform.

Closes https://github.com/astral-sh/uv/issues/5716.
Closes https://github.com/astral-sh/uv/issues/5253.
2024-08-04 14:33:13 -04:00
Charlie Marsh 499c368f1e
Use "pre-release" in prose and `Prerelease` in code (#5697)
## Summary

Closes https://github.com/astral-sh/uv/issues/5630.
2024-08-01 20:56:29 +00:00
Charlie Marsh 4b8a127c54
Avoid persisting `uv add` calls that result in resolver errors (#5664)
## Summary

Closes https://github.com/astral-sh/uv/issues/5622.
2024-07-31 13:27:34 -04:00
konsti a6dfd3953a
Handle universal vs. fork markers with `ResolverMarkers` (#5099)
* Use a dedicated `ResolverMarkers` check in the fork state. This is
better than the `MarkerTree::And(Vec::new())` check.
* Report the timing correct naming universal resolution instead of two
spaces around an empty string when there are no markers.
* On resolution error, show the split that we're in. I'm not sure how to
word this, since we're doing a universal resolution until we fork, so
the trace may contain information from requirements that are not part of
this fork.
2024-07-17 18:59:33 +02:00
Charlie Marsh d9f389a58d
Narrow `requires-python` requirement in resolver forks (#4707)
## Summary

Given:

```text
numpy >=1.26 ; python_version >= '3.9'
numpy <1.26 ; python_version < '3.9'
```

When resolving for Python 3.8, we need to narrow the `requires-python`
requirement in the top branch of the fork, because `numpy >=1.26` all
require Python 3.9 or later -- but we know (in that branch) that we only
need to _solve_ for Python 3.9 or later.

Closes https://github.com/astral-sh/uv/issues/4669.
2024-07-02 12:23:38 +00:00
konsti d9dbb8a4af
Support conflicting URL in separate forks (#4435)
Downstack PR: #4481

## Introduction

We support forking the dependency resolution to support conflicting
registry requirements for different platforms, say on package range is
required for an older python version while a newer is required for newer
python versions, or dependencies that are different per platform. We
need to extend this support to direct URL requirements.

```toml
dependencies = [
  "iniconfig @ 62565a6e1ceac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl ; python_version >= '3.12'",
  "iniconfig @ b3c12c6d70988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl ; python_version < '3.12'"
]
```

This did not work because `Urls` was built on the assumption that there
is a single allowed URL per package. We collect all allowed URL ahead of
resolution by following direct URL dependencies (including path
dependencies) transitively, i.e. a registry distribution can't require a
URL.

## The same package can have Registry and URL requirements

Consider the following two cases:

requirements.in:
```text
werkzeug==2.0.0
werkzeug @ 960bb4017c4aed12b5ed8b78e0153e/Werkzeug-2.0.0-py3-none-any.whl
```
pyproject.toml:
```toml
dependencies = [
  "iniconfig == 1.1.1 ; python_version < '3.12'",
  "iniconfig @ git+https://github.com/pytest-dev/iniconfig@93f5930e668c0d1ddf4597e38dd0dea4e2665e7a ; python_version >= '3.12'",
]
```

In the first case, we want the URL to override the registry dependency,
in the second case we want to fork and have one branch use the registry
and the other the URL. We have to know about this in
`PubGrubRequirement::from_registry_requirement`, but we only fork after
the current method.

Consider the following case too:

a:
```
c==1.0.0
b @ https://b.zip
```
b:
```
c @ https://c_new.zip ; python_version >= '3.12'",
c @ https://c_old.zip ; python_version < '3.12'",
```

When we convert the requirements of `a`, we can't know the url of `c`
yet. The solution is to remove the `Url` from `PubGrubPackage`: The
`Url` is redundant with `PackageName`, there can be only one url per
package name per fork. We now do the following: We track the urls from
requirements in `PubGrubDependency`. After forking, we call
`add_package_version_dependencies` where we apply override URLs, check
if the URL is allowed and check if the url is unique in this fork. When
we request a distribution, we ask the fork urls for the real URL. Since
we prioritize url dependencies over registry dependencies and skip
packages with `Urls` entries in pre-visiting, we know that when fetching
a package, we know if it has a url or not.

## URL conflicts

pyproject.toml (invalid):
```toml
dependencies = [
  "iniconfig @ e96292c7f723f1fa332fe4ed6dfbec/iniconfig-1.1.0.tar.gz",
  "iniconfig @ b3c12c6d70988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl ; python_version < '3.12'",
  "iniconfig @ 62565a6e1ceac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl ; python_version >= '3.12'",
]
```

On the fork state, we keep `ForkUrls` that check for conflicts after
forking, rejecting the third case because we added two packages of the
same name with different URLs.

We need to flatten out the requirements before transformation into
pubgrub requirements to get the full list of other requirements which
may contain a URL, which was changed in a previous PR: #4430.

## Complex Example

a:
```toml
dependencies = [
  # Force a split
  "anyio==4.3.0 ; python_version >= '3.12'",
  "anyio==4.2.0 ; python_version < '3.12'",
  # Include URLs transitively
  "b"
]
```
b:
```toml
dependencies = [
  # Only one is used in each split.
  "b1 ; python_version < '3.12'",
  "b2 ; python_version >= '3.12'",
  "b3 ; python_version >= '3.12'",
]
```
b1:
```toml
dependencies = [
  "iniconfig @ b3c12c6d70988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl",
]
```
b2:
```toml
dependencies = [
  "iniconfig @ 62565a6e1ceac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl",
]
```
b3:
```toml
dependencies = [
  "iniconfig @ e96292c7f723f1fa332fe4ed6dfbec/iniconfig-1.1.0.tar.gz",
]
```

In this example, all packages are url requirements (directory
requirements) and the root package is `a`. We first split on `a`, `b`
being in each split. In the first fork, we reach `b1`, the fork URLs are
empty, we insert the iniconfig 1.1.1 URL, and then we skip over `b2` and
`b3` since the mark is disjoint with the fork markers. In the second
fork, we skip over `b1`, visit `b2`, insert the iniconfig 2.0.0 URL into
the again empty fork URLs, then visit `b3` and try to insert the
iniconfig 1.1.0 URL. At this point we find a conflict for the iniconfig
URL and error.

## Closing

The git tests are slow, but they make the best example for different URL
types i could find.

Part of #3927. This PR does not handle `Locals` or pre-releases yet.
2024-06-26 13:58:23 +02:00
Charlie Marsh 604be9ed71
Use `Preferences` struct in Manifest API (#4496)
## Summary

This is just a bit more consistent with `Overrides` and `Constraints`.
2024-06-24 23:28:55 +00:00
Charlie Marsh cc7c780523
Remove PubGrub dependency from `uv` (#4116)
## Summary

Encapsulates more of the details are `Requires-Python` and PubGrub.

Closes https://github.com/astral-sh/uv/issues/4110.
2024-06-06 23:45:58 +00:00
konsti e4e2590076
Use union of `requires-python` in workspace (#4041)
Follow-up to #4016.

This exposes `Range` and `PubGrubSpecifier` from outside the resolver to
use pubgrub's union creating a dependency edge we don't really want.
2024-06-06 19:21:02 +00:00
Charlie Marsh 1fc6a59707
Remove special-casing for editable requirements (#3869)
## Summary

There are a few behavior changes in here:

- We now enforce `--require-hashes` for editables, like pip. So if you
use `--require-hashes` with an editable requirement, we'll reject it. I
could change this if it seems off.
- We now treat source tree requirements, editable or not (e.g., both `-e
./black` and `./black`) as if `--refresh` is always enabled. This
doesn't mean that we _always_ rebuild them; but if you pass
`--reinstall`, then yes, we always rebuild them. I think this is an
improvement and is close to how editables work today.

Closes #3844.

Closes #2695.
2024-05-28 15:49:34 +00:00
Charlie Marsh 74c494d7dd
Report yanks for cached and resolved packages (#3772)
## Summary

We now show yanks as part of the resolution diagnostics, so they now
appear for `sync`, `install`, `compile`, and any other operations.
Further, they'll also appear for cached packages (but not packages that
are _already_ installed).

Closes https://github.com/astral-sh/uv/issues/3768.

Closes #3766.
2024-05-22 21:21:37 +00:00
konsti 95c9621541
Refactor editables for supporting them in bluejay commands (#3639)
This is split out from workspaces support, which needs editables in the
bluejay commands. It consists mainly of refactorings:

* Move the `editable` module one level up.
* Introduce a `BuiltEditableMetadata` type for `(LocalEditable,
Metadata23, Requirements)`.
* Add editables to `InstalledPackagesProvider` so we can use
`EmptyInstalledPackages` for them.
2024-05-20 16:22:12 +00:00
Ibraheem Ahmed a962a65302
Add routine for verifying two marker trees are disjoint (#3583)
## Summary

Implements https://github.com/astral-sh/uv/issues/3355.
2024-05-15 13:01:05 -04:00
Andrew Gallant d2e7c0554b
uv-resolver: add initial version of universal lock file format (#3314)
This is meant to be a base on which to build. There are some parts
which are implicitly incomplete and others which are explicitly
incomplete. The latter are indicated by TODO comments.

Here is a non-exhaustive list of incomplete things. In many cases, these
are incomplete simply because the data isn't present in a
`ResolutionGraph`. Future work will need to refactor our resolver so
that this data is correctly passed down.

* Not all wheels are included. Only the "selected" wheel for the current
  distribution is included.
* Marker expressions are always absent.
* We don't emit hashes for certainly kinds of distributions (direct
  URLs, git, and path).
* We don't capture git information from a dependency specification.
  Right now, we just always emit "default branch."

There are perhaps also other changes we might want to make to the format
of a more cosmetic nature. Right now, all arrays are encoded using
whatever the `toml` crate decides to do. But we might want to exert more
control over this. For example, by using inline tables or squashing more
things into strings (like I did for `Source` and `Hash`). I think the
main trade-off here is that table arrays are somewhat difficult to read
(especially without indentation), where as squashing things down into a
more condensed format potentially makes future compatible additions
harder.

I also went pretty light on the documentation here than what I would
normally do. That's primarily because I think this code is going to
go through some evolution and I didn't want to spend too much time
documenting something that is likely to change.

Finally, here's an example of the lock file format in TOML for the
`anyio` dependency. I generated it with the following command:

```
cargo run -p uv -- pip compile -p3.10 ~/astral/tmp/reqs/anyio.in --unstable-uv-lock-file
```

And that writes out a `uv.lock` file:

```toml
version = 1

[[distribution]]
name = "anyio"
version = "4.3.0"
source = "registry+https://pypi.org/simple"

[[distribution.wheel]]
url = "2f20c40b45242c0b33774da0e2e34f/anyio-4.3.0-py3-none-any.whl"
hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"

[[distribution.dependencies]]
name = "exceptiongroup"
version = "1.2.1"
source = "registry+https://pypi.org/simple"

[[distribution.dependencies]]
name = "idna"
version = "3.7"
source = "registry+https://pypi.org/simple"

[[distribution.dependencies]]
name = "sniffio"
version = "1.3.1"
source = "registry+https://pypi.org/simple"

[[distribution.dependencies]]
name = "typing-extensions"
version = "4.11.0"
source = "registry+https://pypi.org/simple"

[[distribution]]
name = "exceptiongroup"
version = "1.2.1"
source = "registry+https://pypi.org/simple"

[[distribution.wheel]]
url = "79fe92dd414cadab75055b0ae00b33/exceptiongroup-1.2.1-py3-none-any.whl"
hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"

[[distribution]]
name = "idna"
version = "3.7"
source = "registry+https://pypi.org/simple"

[[distribution.wheel]]
url = "741d8c8280948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl"
hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"

[[distribution]]
name = "sniffio"
version = "1.3.1"
source = "registry+https://pypi.org/simple"

[[distribution.wheel]]
url = "75a9c94214239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl"
hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"

[[distribution]]
name = "typing-extensions"
version = "4.11.0"
source = "registry+https://pypi.org/simple"

[[distribution.wheel]]
url = "936e2092671b43269810cd589ceaf5/typing_extensions-4.11.0-py3-none-any.whl"
hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"
```
2024-04-29 14:03:17 -04:00
Charlie Marsh 1f626bfc73
Move `ExcludeNewer` into its own type (#3041)
## Summary

This makes it easier to add (e.g.) JSON Schema derivations to the type.

If we have support for other dates in the future, we can generalize it
to a `UserDate` or similar.
2024-04-15 20:24:08 +00:00
Charlie Marsh 006379c50c
Add support for URL requirements in `--generate-hashes` (#2952)
## Summary

This PR enables hash generation for URL requirements when the user
provides `--generate-hashes` to `pip compile`. While we include the
hashes from the registry already, today, we omit hashes for URLs.

To power hash generation, we introduce a `HashPolicy` abstraction:

```rust
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HashPolicy<'a> {
    /// No hash policy is specified.
    None,
    /// Hashes should be generated (specifically, a SHA-256 hash), but not validated.
    Generate,
    /// Hashes should be validated against a pre-defined list of hashes. If necessary, hashes should
    /// be generated so as to ensure that the archive is valid.
    Validate(&'a [HashDigest]),
}
```

All of the methods on the distribution database now accept this policy,
instead of accepting `&'a [HashDigest]`.

Closes #2378.
2024-04-10 20:02:45 +00:00