## Summary
Closes https://github.com/astral-sh/uv/issues/17083
Previously having `UV_GIT_LFS` set would cause an error when adding a
non-git requirement such as ```error: `requirement` did not resolve to a
Git repository, but a Git extension (`--lfs`) was provided.```
## Test Plan
Additional test has been added.
## Summary
Follow up to https://github.com/astral-sh/uv/pull/15563
Closes https://github.com/astral-sh/uv/issues/13485
This is a first-pass at adding support for conditional support for Git
LFS between git sources, initial feedback welcome.
e.g.
```
[tool.uv.sources]
test-lfs-repo = { git = "https://github.com/zanieb/test-lfs-repo.git", lfs = true }
```
For context previously a user had to set `UV_GIT_LFS` to have uv fetch
lfs objects on git sources. This env var was all or nothing, meaning you
must always have it set to get consistent behavior and it applied to all
git sources. If you fetched lfs objects at a revision and then turned
off lfs (or vice versa), the git db, corresponding checkout lfs
artifacts would not be updated properly. Similarly, when git source
distributions were built, there would be no distinction between sources
with lfs and without lfs. Hence, it could corrupt the git, sdist, and
archive caches.
In order to support some sources being LFS enabled and other not, this
PR adds a stateful layer roughly similar to how `subdirectory` works but
for `lfs` since the git database, the checkouts and the corresponding
caching layers needed to be LFS aware (requested vs installed). The
caches also had to isolated and treated entirely separate when handling
LFS sources.
Summary
* Adds `lfs = true` or `lfs = false` to git sources in pyproject.toml
* Added `lfs=true` query param / fragments to most relevant url structs
(not parsed as user input)
* In the case of uv add / uv tool, `--lfs` is supported instead
* `UV_GIT_LFS` environment variable support is still functional for
non-project entrypoints (e.g. uv pip)
* `direct-url.json` now has an custom `git_lfs` entry under VcsInfo
(note, this is not in the spec currently -- see caveats).
* git database and checkouts have an different cache key as the sources
should be treated effectively different for the same rev.
* sdists cache also differ in the cache key of a built distribution if
it was built using LFS enabled revisions to distinguish between non-LFS
same revisions. This ensures the strong assumption for archive-v0 that
an unpacked revision "doesn't change sources" stays valid.
Caveats
* `pylock.toml` import support has not been added via git_lfs=true,
going through the spec it wasn't clear to me it's something we'd support
outside of the env var (for now).
* direct-url struct was modified by adding a non-standard `git_lfs`
field under VcsInfo which may be undersirable although the PEP 610 does
say `Additional fields that would be necessary to support such VCS
SHOULD be prefixed with the VCS command name` which could be interpret
this change as ok.
* There will be a slight lockfile and cache churn for users that use
`UV_GIT_LFS` as all git lockfile entries will get a `lfs=true` fragment.
The cache version does not need an update, but LFS sources will get
their own namespace under git-v0 and sdist-v9/git hence a cache-miss
will occur once but this can be sufficient to label this as breaking for
workflows always setting `UV_GIT_LFS`.
## Test Plan
Some initial tests were added. More tests likely to follow as we reach
consensus on a final approach.
For IT test, we may want to move to use a repo under astral namespace in
order to test lfs functionality.
Manual testing was done for common pathological cases like killing LFS
fetch mid-way, uninstalling LFS after installing an sdist with it and
reinstalling, fetching LFS artifacts in different commits, etc.
PSA: Please ignore the docker build failures as its related to depot
OIDC issues.
---------
Co-authored-by: Zanie Blue <contact@zanie.dev>
Co-authored-by: konstin <konstin@mailbox.org>
Part of https://github.com/astral-sh/uv/issues/4392
We shouldn't link to PyPI, and dropping the workspace-level
documentation link should mean that we get the auto-generated `docs.rs`
links.
Resolves https://github.com/astral-sh/uv/issues/16719
`uv add` collapses multiple spaces before inline comments in
`[project.dependencies]`, causing unrelated diffs and moving comments
onto the wrong columns. This diff captures the exact whitespace padding
that preceded each end-of-line comment when parsing the array and reuses
it when formatting.
---------
Co-authored-by: konstin <konstin@mailbox.org>
## Summary
This PR adds an `exclude-dependencies` setting that allows users to omit
a dependency during resolution. It's effectively a formalized version of
the `flask ; python_version < '0'` hack that we've suggested to users in
various issues.
Closes#12616.
<!--
Thank you for contributing to uv! To help us out with reviewing, please
consider the following:
- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->
## Summary
Fixes#16285
## Test Plan
<!-- How was it tested? -->
## Summary
Fixes [1633](https://github.com/astral-sh/uv/issues/16133). Preserves
comments preceding "version = ..." line when uv version --bump is ran
## Test Plan
Added IT test
---------
Co-authored-by: konsti <konstin@mailbox.org>
## Summary
This ended up being a bit more complex, similar to `package = false`,
because we need to understand the editable status _globally_ across the
workspace based on the packages that depend on it.
Closes https://github.com/astral-sh/uv/issues/15686.
## Summary
This was fixed in https://github.com/astral-sh/uv/pull/15161, then
reverted as it regressed the error handling. I've re-applied the change
here, but moved the error handling to the runtime, rather than
parse-time. I think this is slightly worse in that we no longer include
the originating source code snippet, but it at least gives us the
expected behavior :(
Closes https://github.com/astral-sh/uv/issues/15124.
## Summary
`match-runtime` can be explicitly specified, and if it's `false` it
should behave the same way as if it's omitted.
## Test Plan
Added snapshot test
## Summary
It would be nice if this rendered as
`[tool.uv.extra-build-dependencies]` and `[extra-build-dependencies]`
(in `uv.toml`), but this is at least correct.
Closes https://github.com/astral-sh/uv/issues/15124.
## Summary
Make the use of `Self` consistent. Mostly done by running `cargo clippy
--fix -- -A clippy::all -W clippy::use_self`.
## Test Plan
<!-- How was it tested? -->
No need.
## Summary
This is an alternative to https://github.com/astral-sh/uv/pull/14944
that functions a little differently. Rather than adding separate
strategies, you can instead say:
```toml
[tool.uv.extra-build-dependencies]
child = [{ requirement = "anyio", match-runtime = true }]
```
Which will then enforce that `anyio` uses the same version as in the
lockfile.
## Summary
The basic problem here is that when we had multiple items in an inline
array, and that array expanded to multiple lines, we accidentally
changed the indentation part-way through due to how prefixes work in the
TOML.
Here's Claude's explanation of the root cause, which I find pretty
decent:
```
Here's what happened step by step:
1. First item ("iniconfig"): Has empty prefix "" → indentation_prefix stays None → uses default 4 spaces
2. Second item ("ruff"): Has empty prefix "" → indentation_prefix stays None → uses default 4 spaces
3. Third item ("typing-extensions"): Has prefix " " (single space from inline format) → indentation_prefix becomes
Some(" ") → uses only 1 space!
This produced:
[dependency-groups]
dev = [
"iniconfig>=2.0.0",
"ruff",
"typing-extensions", # ← Only 1 space instead of 4!
]
Why the Third Item Had a Different Prefix
In inline arrays like ["ruff", "typing-extensions"], the items are separated by commas and spaces. When parsed by
the TOML library:
- "ruff" has no prefix (it comes right after [)
- "typing-extensions" has a single space prefix (the space after the comma)
The Fix
Moving the indentation calculation outside the loop ensures it's calculated only once:
// Calculate indentation ONCE before the loop
if let Some(first_item) = deps.iter().next() {
let decor_prefix = /* get prefix from first item */
indentation_prefix = (!decor_prefix.is_empty()).then_some(decor_prefix.to_string());
}
// Now use the same indentation for ALL items
for item in deps.iter_mut() {
// Apply consistent indentation to every item
}
This ensures all items get the same indentation (4 spaces by default when converting from inline arrays), producing
the correct output:
[dependency-groups]
dev = [
"iniconfig>=2.0.0",
"ruff",
"typing-extensions", # ← Correct 4-space indentation
]
The bug only affected arrays being converted from inline to multiline format, where different items might have
different residual formatting from their inline representation.
```
Closes#14961.
---------
Co-authored-by: Zanie Blue <contact@zanie.dev>
Replaces https://github.com/astral-sh/uv/pull/14092
Adds `tool.uv.extra-build-dependencies = {package = [dependency, ...]}`
which extends `build-system.requires` during package builds.
These are lowered via workspace sources, are applied to transitive
dependencies, and are included in the wheel cache shard hash.
There are some features we need to follow-up on, but are out of scope
here:
- Preferring locked versions for build dependencies
- Settings for requiring locked versions for build depencies
There are some quality of life follow-ups we should also do:
- Warn on `extra-build-dependencies` that do not apply to any packages
- Add test cases and improve error messaging when the
`extra-build-dependencies` resolve fails
-------
There ~are~ were a few open decisions to be made here
1. Should we resolve these dependencies alongside the
`build-system.requires` dependencies? Or should we resolve separately?
(I think the latter is more powerful? because you can override things?
but it opens the door to breaking your build)
2. Should we install these dependencies into the same environment? Or
should we layer it on top as we do elsewhere? (I think it's fine to
install into the same environment)
3. Should we respect sources defined in the parent project? (I think
yes, but then we need to lower the dependencies earlier — I don't think
that's a big deal, but it's not implemented)
4. Should we respect sources defined in the child project? (I think no,
this gets really complicated and seems weird to allow)
5. Should we apply this to transitive dependencies? (I think so)
---------
Co-authored-by: Aria Desires <aria.desires@gmail.com>
Co-authored-by: konstin <konstin@mailbox.org>
## Summary
A little nuanced, but... When you add multiple `--index` URLs on the CLI
(e.g., in `uv pip install`), we check the first-provided index, then the
second index, etc. However, when we _write_ those URLs to the
`pyproject.toml` in `uv add`, we were adding them in reverse-order. We
now add them in a way that preserves the priority order.
Closes https://github.com/astral-sh/uv/issues/14817.
## Summary
This should give us some performance and error message improvements.
---------
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
Co-authored-by: Zanie Blue <contact@zanie.dev>
We currently treat path sources as virtual if they do not specify a
build system, which is surprising behavior. This PR updates the behavior
to treat path sources as packages unless the path source is explicitly
marked as `package = false` or its own `tool.uv.package` is set to
`false`.
Closes#12015
---------
Co-authored-by: Zanie Blue <contact@zanie.dev>
If a user specifies `-e /path/to/dir` and `/path/to/dir` in a `uv pip
install` command, we want the editable to "win" (rather than erroring
due to conflicting URLs). Unfortunately, this behavior meant that when
you requested a package as editable and non-editable in conflicting
groups, the editable version was _always_ used. This PR modifies the
requisite types to use `Option<bool>` rather than `bool` for the
`editable` field, so we can determine whether a requirement was
explicitly requested as editable, explicitly requested as non-editable,
or not specified (as in the case of `/path/to/dir` in a
`requirements.txt` file). In the latter case, we allow editables to
override the "unspecified" requirement.
If a project includes a path dependency twice, once with `editable =
true` and once without any `editable` annotation, those are now
considered conflicting URLs, and lead to an error, so I've marked this
change as breaking.
Closes https://github.com/astral-sh/uv/issues/14139.
<!--
Thank you for contributing to uv! To help us out with reviewing, please
consider the following:
- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->
## Summary
remove redundant words in comment
<!-- What's the purpose of the change? What does it do, and why? -->
## Test Plan
<!-- How was it tested? -->
Signed-off-by: jingchanglu <jingchanglu@outlook.com>