Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constraint flag for uv add #6518

Open
yehoshuadimarsky opened this issue Aug 23, 2024 · 13 comments
Open

Constraint flag for uv add #6518

yehoshuadimarsky opened this issue Aug 23, 2024 · 13 comments
Labels
enhancement New feature or improvement to existing functionality

Comments

@yehoshuadimarsky
Copy link

Hi, can we instead add a new flag -c / --constraint to uv add, so that you can pass in constraint files directly? I think currently you can do this by adding a constraint to a requirements.txt file, then running uv add --requirements requirements.txt, but this would embed it directly in the command.

My specific use case is using Apache Airflow which only supports pip (not Poetry etc) because it basically requires constraint files, see https://github.com/apache/airflow/blob/main/README.md#installing-from-pypi

That way, I can do (copying from their example):

uv add 'apache-airflow==2.10.0' \
 --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-2.10.0/constraints-3.8.txt"

Thanks.

@yehoshuadimarsky
Copy link
Author

yehoshuadimarsky commented Aug 23, 2024

#6275 (comment)

You need to add that constraint file to tool.uv.constraint_dependencies? It needs to be tracked in the project. uv add --constraint could perhaps do that for you, but it's going to apply to all of your dependencies.

That's fine, in fact that's probably the best behavior, that the constraint applies to all dependencies. But in line with my Airflow use case, it'd be great if we can specify a URL for tool.uv.constraint_dependencies, not just a file that we have to download and save

@yehoshuadimarsky
Copy link
Author

cc @potiuk

@zanieb
Copy link
Member

zanieb commented Aug 23, 2024

Can you not specify a URL in constraint_dependencies? I presumed that'd just work.

@zanieb zanieb added the enhancement New feature or improvement to existing functionality label Aug 23, 2024
@yehoshuadimarsky
Copy link
Author

Sorry I don't think tool.uv.constraint_dependencies is a valid section yet (if it is, apologies for my mistake). I'm just saying that if/when it becomes a valid section, it'd be great if it could specify not only dependencies, but a URL that points to a valid constraint file (like Airflow's). If this is already assumed/included, please disregard.

@zanieb
Copy link
Member

zanieb commented Aug 23, 2024

Sorry — constraint-dependencies. We're missing documentation for this one for some reason.

@yehoshuadimarsky
Copy link
Author

How? I tried running uv lock after adding this to pyproject.toml,

[tool.uv]
constraint-dependencies = ["https://raw.githubusercontent.com/apache/airflow/constraints-2.10.0/constraints-3.8.txt"]

but got

warning: Failed to parse `pyproject.toml` during settings discovery:
  TOML parse error at line 16, column 27
     |
  16 | constraint-dependencies = ["https://raw.githubusercontent.com/apache/airflow/constraints-2.10.0/constraints-3.8.txt"]
     |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  URL requirement must be preceded by a package name. Add the name of the package before the URL (e.g., `package_name @ https://...`).
  https://raw.githubusercontent.com/apache/airflow/constraints-2.10.0/constraints-3.8.txt
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: Failed to parse: `pyproject.toml`
  Caused by: TOML parse error at line 16, column 27
   |
16 | constraint-dependencies = ["https://raw.githubusercontent.com/apache/airflow/constraints-2.10.0/constraints-3.8.txt"]
   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
URL requirement must be preceded by a package name. Add the name of the package before the URL (e.g., `package_name @ https://...`).
https://raw.githubusercontent.com/apache/airflow/constraints-2.10.0/constraints-3.8.txt
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

@zanieb
Copy link
Member

zanieb commented Aug 23, 2024

Ah sorry I misunderstood — yes this requires the constraints to be unpacked into a list. I'm not sure it makes sense to use a remote file here? We'd need to download it on every uv operation. Could we just unpack it into this setting on uv add?

@yehoshuadimarsky
Copy link
Author

I'm not sure it makes sense to use a remote file here? We'd need to download it on every uv operation.

I get the overhead hit, but is it any different from uv pip install -c https://raw.githubusercontent.com/apache/airflow/constraints-2.10.0/constraints-3.8.txt apache-airflow, which works and is valid? I think it's acceptable to allow a URL here

Could we just unpack it into this setting on uv add?

Yes, that could be a good fallback, if you decide not to support saving the URL itself in pyproject.toml. I guess would be good to at least auto-generate a comment saying "constraints packages were obtained from the user supplied URL <URL>" or something like that, so they can trace it back to the source

@zanieb
Copy link
Member

zanieb commented Aug 23, 2024

Yes, it's different because you uv pip install once, but with the project interface we check if the environment is up-to-date on every invocation of uv run so we can't have dynamic metadata like this (and, if we cache it, people complain when it's not checked).

@yehoshuadimarsky
Copy link
Author

I see, that makes sense. So can we at least add the flag --constraint to uv add that would

  1. read the URL
  2. populate tool.uv.constraint-dependencies, along with a comment indicating where it came from
  3. then proceed as normal?

I guess there are some outstanding questions about what the expected behavior should be in these scenarios:

  • uv add -c <url1> -c <url2> - what happens if they conflict?
  • uv add -c <url1>, then uv add -c <url2> - what happens if they conflict? Or, does the second invocation wipe out (replace) the first constraints, or just add to it?

@zanieb
Copy link
Member

zanieb commented Aug 23, 2024

Yeah that sounds nice. We should probably support it for local files first. I'm a little hesitant on automatically tracking the URL but maybe it'd be okay.

I think they'd be combined as we would normally combine constraint files when they overlap (which I think means we'd raise an error if it results in unsolvable dependencies).

@torran-g
Copy link

torran-g commented Oct 10, 2024

FWIW I have exactly the same use case as @yehoshuadimarsky and I'd be very pleased to see his suggestion implemented.

I'd add that running uv run or uv lock would need to adhere to the remote constraint file for all of the other dependencies in the tree that aren't specified in the pyproject.toml file; so that our local environment matches the constrained Airflow environment.

Currently, I am specifing a minimal list of dependencies in pyproject.toml without specifying versions for the packages which are included in Airflow's constraints file, then using the uv pip compile command with the --constraint flag specified to generate a compatible requirements.txt file. I can then reference the requirements.txt file when using the uv pip sync and uv pip install commands to install them in a local environment. But I'd prefer it if uv managed the package and local environment itself, and uv.lock adhered to the constraints, so I can use uv run to run my test suite.

The specific commands I'm using currently.

> uv pip compile pyproject.toml --constraint https://raw.githubusercontent.com/apache/airflow/constraints-2.9.2/constraints-3.11.txt --no-strip-extras --emit-index-url --all-extras --output-file requirements.txt -q
> uv pip sync requirements.txt
> uv pip install --requirement requirements.txt

A separate, but related, feature request, would be an option to write the constraint file used to the top of the requirements.txt file. As described in point 3 of these MWAA docs.

@slumbi
Copy link

slumbi commented Jan 11, 2025

This is a workaround, but at my company , in our airflow project we use Taskfile ( makefile alternative ) to manage the constrained airflow dependencies, and do not rely on uv add.

requirements.in contains the dependencies and constraints, like

-c https://raw.githubusercontent.com/apache/airflow/constraints-2.10.4/constraints-3.10.txt

boto3                                    >1.34, <1.36
botocore                                 >1.34, <1.36
s3transfer == 0.10.4

apache-airflow==2.10.4
apache-airflow-providers-amazon==9.1.0

and Taskfile.yml contains the commands for dependency management:

# https://taskfile.dev
version: '3'

vars:
  REQIN: requirements.in
  REQOUT: requirements.txt.out

tasks:
  default:
    cmds:
      - task -l
    silent: true

  install:
    desc: Compile and install requirements
    deps: [compile]
    aliases: [i]
    cmds:
      - uv pip install -r {{ .REQOUT }}

  compile:
    desc: Compile python requirements
    aliases: [c]
    cmds:
      - uv pip compile {{ .REQIN }}  > {{ .REQOUT }}

  sync:
    desc: Sync installed packages with requirements file
    aliases: [s]
    cmds:
      - uv pip sync {{ .REQOUT }}

Then instead of uv sync we simply do :

  • task c or task compile which will compile dependencies
  • task i or task install which will compile + install dependencies
  • task s or task sync wihch will sync compiled requirements with virtual env

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or improvement to existing functionality
Projects
None yet
Development

No branches or pull requests

4 participants