Explicit index not respected for transitive dependency
Hey, thanks for delivering explicit indexes in #7481 ❤️ I'm trying this with uv built from the last commit (e71b1d0c), but I have a problem with transitive dependencies & explicit index.
Scenario: my-app depends on internal pkg a, which declares a dependency on (internal) package b.
In my app project.toml, I define the index plus I set sources for both pkg a & b. But then uv lock` gives me
Because b was not found in the package registry ...
So it's ignoring the source definition when resolving a transitive dependency.
[[tool.uv.index]]
name = "my-internal-index"
url = "..."
explicit = true
[tool.uv.sources]
a = { index = "my-internal-index" }
b = { index = "my-internal-index" }
[project.dependencies]
a = { version = "1.0" } # `a` declares a dependency on `b`
Sources only apply to dependencies that are declared in the project itself. In this case, you'd need to define b as a dependency.
Yep, that works.
Though, is it a good approach? my-app doesn't really depend on b, only transitively. So if a removes the dependency on b in the future, I'll be left with an unused dependency. For this reason, I'll also get a warning by deptry that the dependency is not used in my code.
I don't know if it applies here, but this handling of transitive dependencies is the primary driver for the "glob pattern-based source declaration" functionality that exists in PDM and others have implemented using poetry plugins described e.g. here. The idea is that in corporate environments, where it's common to enforce a namespace for internal packages, this makes it easy to setup a declaration that handles pinning transitive internal dependencies to a particular repository.
just echoing that there is some desire to have a way to inform a package manager about how to handle particular transitive dependencies.
@juzna You may be better off though removing the explicit = true so that all packages are checked on your internal index first. That's probably a fair workaround, and improves your security.
We're also running into this issue. We have a library that depends on torch, so for that library we have set up as in the docs, and that works.
[tool.uv.sources]
torch = { index = "pytorch" }
[[tool.uv.index]]
name = "pytorch"
url = "https://download.pytorch.org/whl/cpu"
explicit = true
Now when this library is used in an application, I'm getting Because there is no version of torch{platform_system == 'Linux'}==2.5.0+cpu..., even when the same index is also added in the application's pyproject.toml. Making the index non-explicit also doesn't work, because the torch index contains some older version of requests which then blocks us from fetching the required requests from the default index. It does work with non-explicit index and --index-strategy unsafe-first-match but we'd prefer to avoid using the unsafe option.
I would also be in favor of an improvement of this corporate use case.
My package A depends on package B from private index which itself depends on C from private index.
No way to make it works from A pyproject.toml without explicit = true that we don't want as it puts unnecessary pressure on our internal index, only used for our packages.
Option 2 of defining transitive dependencies like C directly in A is not very clean either.
Hey guys, do you have any further thoughts on this? Using uv with multiple packages from separate indices is somewhat painful right now do to a lack of configurability of such a feature.
Example:
- project depends on
rospyfrom their index, which has other transitive dependencies in their custom index - project depends on
custom-libfrom an internal index, which has other transitive dependencies in the internal index - both depend on
numpy(silly example) from the PyPi index
How do we resolve such dependencies without declaring both the rospy index and custom-lib index as non-explicit? Marking both as non-explicit leads to poor resolution from unexpected indices.
Do you have any plans to add some options to resolve it ?
This missing functionality is problematic for me, as well, so +1, but I'm going to go a bit further and say that uv pip install <package> should also honor the source configurations. The common use case for this is plugins: my (proprietary) app employs a plugin package architecture. Devs frequently need to test the app locally with different plugin packages installed (all of which are arbitrary and optional, so not dependencies of the main app at all). Currently, we can't simply install the package with uv pip install as one would hope, even if we assign those packages to our private package index in [tool.uv.sources]. That should work.
Note: currently we work around this by installing from the repo URL or a local clone, but this approach requires extra care, as it introduces the risk that we're testing with a build of the plugin package that doesn't correspond to the latest release.
+1 from me for adding this fnctional. @charliermarsh advice from his answer works for me but in more complicated cases i see this approach may cause troubles in managing my company internal dependencies
+1
Can't properly handle installing nightly torch for CUDA Toolkit 13.0:
[project.optional-dependencies]
cu128 = [ "torch==2.7.1" ]
cu129 = [ "torch==2.8.0" ]
cu130 = [ "torch==2.9.0.dev20250909+cu130" ]
[tool.uv.sources]
torch = [
{ index = "cu128", extra = "cu128" },
{ index = "cu129", extra = "cu129" },
{ index = "cu130", extra = "cu130" }
]
[[tool.uv.index]]
name = "cu128"
url = "https://download.pytorch.org/whl/cu128"
explicit = true
[[tool.uv.index]]
name = "cu129"
url = "https://download.pytorch.org/whl/cu129"
explicit = true
[[tool.uv.index]]
name = "cu130"
url = "https://download.pytorch.org/whl/nightly/cu130"
explicit = true
Making non-explicit all indices is kinda scary
Ran into the same issue also in a corporate setting where only some package should be fetched from the private index. Would appreciate seeing an improvement of that usecase here.
+1
+1, ran into this issue today as well
(Thanks for all u do)
+1
@KochankovID @tekeinhor @karim-moon
Just a quick note: on many projects, maintainers prefer avoiding “+1” comments since they notify everyone without adding new information. Using the 👍 reaction on the original post is usually the recommended way to show support and keep the thread clean and useful for maintainers.
Thanks!