3

I'm developing two Python projects:

  • xxx: A Python library I maintain, hosted on GitHub.
  • yyy: An open-source project that depends on xxx.

In yyy's pyproject.toml, I declare the dependency as:

[tool.uv.sources]
xxx = { git = "git+https://github.com/myuser/xxx.git" }

This works well for others who clone yyy — they get the correct version of xxx from GitHub. However during development, I want to use a local copy of xxx (e.g., ~/xxx) so I can test changes in yyy without pushing to GitHub each time.

I'd like a solution that:

  • Lets me use a local path for xxx during development.
  • Doesn’t require me to change pyproject.toml before every commit.
  • Keeps yyy portable and installable via GitHub for others.

Is there a clean way to override the Git-based dependency locally (perhaps with a .gitignored file or config), while keeping pyproject.toml untouched?

I'm using uv as my Python package manager.

Any best practices or workflows for this setup?

2
  • You can keep pyproject.toml modified locally and do not have to change it before every commit. Commented Oct 26 at 14:58
  • I might be missing something, but why not use the pip interface and install your local version of the package over the pyproject.toml version? eg. uv sync && uv pip install ./xxx. See docs.astral.sh/uv/getting-started/features/#the-pip-interface Commented Oct 29 at 0:25

2 Answers 2

2

I don't have a test install for your case right now, and I also strongly recommend properly versioning your dependency to PyPI and giving a clear range of compatible versions over giving just a source repo, especially if you don't provide any version and always rely on the HEAD as it's extremely difficult for users to audit your package and it could be frustrating for them to use it in restricted environments and cause debugging headaches for them and yourself

That said, using dependency groups and passing --only-group to force the use of your local development group might be all you need .. you can nest groups to avoid duplicating other dependencies

uv build --only-group local
[dependency-groups]
normal = [
  "xxx"
  {include-group = "build"}
]
local = [
  "xxx_local"
  {include-group = "build"}
]
build = [
  other shared deps here
]

[tool.uv]
default-groups = ["normal"]

[tool.uv.sources]
xxx = { git = "git+https://github.com/myuser/xxx.git" }
xxx_local = { path = "~/xxx" }

Or you can supply a completely fresh uv.toml (uv-local.toml?) via --config-file where you just set the path to the local path

Plausibly this requires splitting all the uv settings from pyproject.toml into a default uv.toml or it may temporarily ignore the uv content, potentially benefiting your case (I'm not certain, the docs say "While uv configuration can be included in a pyproject.toml file, it is not allowed in this context.")

If you build+test as part of a larger script, many tools accept - to pass the config via stdin, which may be easier too

Sign up to request clarification or add additional context in comments.

3 Comments

Using dependency groups is a good option. I would recommend against doing any sort of name mangling to the xxx package and instead declare the two groups as conflicting, which then allows you to differentiate the sources by group in the uv.sources section like this
@matt729 I think that would make a stronger Answer than mine if you'd like to add it! otherwise thanks, I'll go ahead and make the edit
Thank you both for your answers! I found it necessary to adopt @matt729 's suggestion. github.com/Daniel-Chin/sync-my-youtube-playlists/blob/… Otherwise the mismatch between package name "xxx_local" vs "xxx" is a problem. Could either of you try posting / editing a final answer?
1
+50

I think uv's --with-editable would help here.

Let's assume you have xxx and yyy both cloned locally, to ~/xxx and ~/yyy respectively. Within ~/yyy you should find that:

uv run --with-editable ../xxx python -c "import xxx; print(xxx)"

will run in an environment in which your local clone of xxx is used. It won't touch yyy's pyproject.toml or uv.lock.

This also works with longer dependency chains too; so if you have zzz depending on yyy depending on xxx, you can use --with-editable when running commands in zzz to test your local changes in xxx.

Note that this isn't "sticky", in the sense that if you subsequently do a bare uv run python ... then you'll use the "proper" version of xxx rather than the local version again.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.