uv icon indicating copy to clipboard operation
uv copied to clipboard

Specify editable files in pyproject.toml

Open Andrew-Chen-Wang opened this issue 1 year ago • 7 comments

I have a pip compiled requirements file specifying a few local packages:

requirements file
# This file was autogenerated by uv via the following command:
#    uv pip compile pyproject.toml -o requirements_dev.txt
annotated-types==0.6.0
    # via pydantic
anyio==4.3.0
    # via
    #   starlette
    #   watchfiles
asttokens==2.4.1
    # via stack-data
click==8.1.7
    # via
    #   tasks
    #   uvicorn
decorator==5.1.1
    # via ipython
executing==2.0.1
    # via stack-data
fastapi==0.109.2
    # via web
h11==0.14.0
    # via uvicorn
httptools==0.6.1
    # via uvicorn
idna==3.6
    # via anyio
iniconfig==2.0.0
    # via pytest
ipython==8.21.0
jedi==0.19.1
    # via ipython
matplotlib-inline==0.1.6
    # via ipython
models @ file:///${PROJECT_ROOT}/projects/backend/libs/models
    # via web
orjson==3.9.14
    # via web
packaging==23.2
    # via pytest
parso==0.8.3
    # via jedi
pexpect==4.9.0
    # via ipython
pluggy==1.4.0
    # via pytest
prompt-toolkit==3.0.43
    # via ipython
ptyprocess==0.7.0
    # via pexpect
pure-eval==0.2.2
    # via stack-data
pydantic==2.6.1
    # via fastapi
pydantic-core==2.16.2
    # via pydantic
pygments==2.17.2
    # via ipython
pytest==8.0.1
    # via
    #   models
    #   web
python-dotenv==1.0.1
    # via uvicorn
pyyaml==6.0.1
    # via uvicorn
ruff==0.2.2
six==1.16.0
    # via asttokens
sniffio==1.3.0
    # via anyio
sqlalchemy==2.0.27
    # via models
stack-data==0.6.3
    # via ipython
starlette==0.36.3
    # via fastapi
tasks @ file:///${PROJECT_ROOT}/projects/tools/tasks
traitlets==5.14.1
    # via
    #   ipython
    #   matplotlib-inline
typing-extensions==4.9.0
    # via
    #   fastapi
    #   pydantic
    #   pydantic-core
    #   sqlalchemy
uvicorn==0.27.1
    # via web
uvloop==0.19.0
    # via uvicorn
watchfiles==0.21.0
    # via uvicorn
wcwidth==0.2.13
    # via prompt-toolkit
web @ file:///${PROJECT_ROOT}/projects/backend/services/web
websockets==12.0
    # via uvicorn

I then have a separate requirements file that allows me to install the local packages as editable even though they're already statically defined in the pip compiled requirements file:

-r bin/requirements-dev.txt

-e file:///${PROJECT_ROOT}/projects/tools/tasks
-e file:///${PROJECT_ROOT}/projects/backend/services/web

This then raises:

(.venv) andrew@Andrew andrew % uv pip install -r requirements.txt
Audited 44 packages in 4ms
(.venv) andrew@Andrew andrew % uv pip install -r requirements.txt
   Built file:///Users/andrew/projects/tools/tasks
   Built file:///Users/andrew/projects/backend/services/web                                
Built 2 editables in 502ms
Resolved 44 packages in 9ms
error: Failed to determine installation plan
  Caused by: Detected duplicate package in requirements: tasks

I have it set up like this so that I can use pip compile to ensure all local packages' dependencies in the monorepo are on the same version across local packages. I think there's a workaround with hatch (ref https://github.com/pypa/hatch/issues/588), but since I do uv pip install -r requirements.txt instead of with hatch, the post install won't ever run (I've never used hatch, so maybe I'm not following it right).

Is there a way with uv and any build system that can let me install editable files by specifying in pyproject.toml?

Andrew-Chen-Wang avatar Feb 21 '24 20:02 Andrew-Chen-Wang

That's an interesting use-case. I'd need to think on the "right" way to do this.

charliermarsh avatar Feb 21 '24 20:02 charliermarsh

I mainly invented --unsafe-package flag for this specific use case and would do,

uv pip compile pyproject.toml -o requirements_dev.txt --unsafe-package web --unsafe-package tasks

hmc-cs-mdrissi avatar Feb 21 '24 20:02 hmc-cs-mdrissi

@hmc-cs-mdrissi - Sorry for my ignorance, does --unsafe-package just omit the package from the outputs?

charliermarsh avatar Feb 22 '24 16:02 charliermarsh

Okay yeah, that appears to be the case. We could support that without much trouble...

charliermarsh avatar Feb 22 '24 16:02 charliermarsh

Would it still include the package's dependencies in the pip compile? Thinking about what Mehdi says, I'm lead to believe yes. Thanks both y'all!

Andrew-Chen-Wang avatar Feb 22 '24 17:02 Andrew-Chen-Wang

Unsafe package has no effect on resolution and dependencies are all calculated same as before. It only affects the file generation by removing the exact dependencies mentioned. It should be equivalent to a post processing step that removes packages requested as unsafe.

hmc-cs-mdrissi avatar Feb 22 '24 17:02 hmc-cs-mdrissi

👍 Thanks @hmc-cs-mdrissi.

charliermarsh avatar Feb 22 '24 17:02 charliermarsh

My suggestion now is to use --unsafe-package (an alias of --no-emit-package) for these! Supported in the next release.

charliermarsh avatar Feb 25 '24 03:02 charliermarsh

Thank you!

For future ref, this was added in https://github.com/astral-sh/uv/pull/1935 or commit https://github.com/astral-sh/uv/commit/0476bca272e0a9e06e2819bee85821f4e864725d

Andrew-Chen-Wang avatar Feb 25 '24 05:02 Andrew-Chen-Wang