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
Support remote https://
requirements files (#1332)
#2081
Conversation
Thanks! I've been conflicted on whether to support this but ultimately it does seem reasonable.
Using a permalink to a GitHub repo is totally fine and consistent with some of our other tests. |
Ready for review now in my eyes. I tried replacing the e.g.
/requirements.txt
|
Okay cool, thank you! Acknowledging that it's now blocked on me reviewing. |
With the change to switch to uv, we skipped constraints being used in CI image - in effect all PR were not using constraints, but they were using not constraint dependencues but lowest-direct mode of installation so direct dependencies would not be upgraded in such case, only the transitive ones, so the risk of failure was anyhow small even if someone released a new, breakong dependency. The reason is that `uv` currently does not support installing constraints from URL. We had been silently failing back to the "no-constraints" way in such case (this is default mode if for any reason constraint build fail in such case. It introduced the risk that in case 3rd-party breaking dependency was released it would also start breaking regular PRs, not only the "canary" build. We fix it by downloading constraints locally when they are remote and using them from there. While this is being worked on in astral-sh/uv#2081 and likely to land in uv 0.1.14, it's also a good idea to actually download the constraints and keep them around - this might be handy if you want to later use constraints to install "golden" set of dependencies wihtout necessity to build the right URL - you can always use `${HOME}/constraints.txt`. This PR fixes it and also changes the fallback mechanism to perform the lowest-direct upgrade only in case the constraint build fails, rather than always run the lowest-dirct upgrade even if constraints install works fine - this will make sure that most PRs are using exactly the constraint version of the dependencies (at least the version of constraints that were generated last time when pyproject.toml changed).
Just to add to the weight here: This is also Highly used feature in apache-airflow - if users of airflow would like to use the recommended installation option - they cannot use it directly now with uv - they need to download the constraints first. This caused a small hicc-up in our CI images in Airflow (as I did not notice that remove constraints installation was not working with uv. I fix it in apache/airflow#37845 (and generally downloading constraints to CI image is a good idea) - but users trying to do reproducible installation of Airlfow should be able to use the URL, so big cheering on that one :). |
With the change to switch to uv, we skipped constraints being used in CI image - in effect all PR were not using constraints, but they were using not constraint dependencues but lowest-direct mode of installation so direct dependencies would not be upgraded in such case, only the transitive ones, so the risk of failure was anyhow small even if someone released a new, breakong dependency. The reason is that `uv` currently does not support installing constraints from URL. We had been silently failing back to the "no-constraints" way in such case (this is default mode if for any reason constraint build fail in such case. It introduced the risk that in case 3rd-party breaking dependency was released it would also start breaking regular PRs, not only the "canary" build. We fix it by downloading constraints locally when they are remote and using them from there. While this is being worked on in astral-sh/uv#2081 and likely to land in uv 0.1.14, it's also a good idea to actually download the constraints and keep them around - this might be handy if you want to later use constraints to install "golden" set of dependencies wihtout necessity to build the right URL - you can always use `${HOME}/constraints.txt`. This PR fixes it and also changes the fallback mechanism to perform the lowest-direct upgrade only in case the constraint build fails, rather than always run the lowest-dirct upgrade even if constraints install works fine - this will make sure that most PRs are using exactly the constraint version of the dependencies (at least the version of constraints that were generated last time when pyproject.toml changed).
With the change to switch to uv, we skipped constraints being used in CI image - in effect all PR were not using constraints, but they were using not constraint dependencues but lowest-direct mode of installation so direct dependencies would not be upgraded in such case, only the transitive ones, so the risk of failure was anyhow small even if someone released a new, breakong dependency. The reason is that `uv` currently does not support installing constraints from URL. We had been silently failing back to the "no-constraints" way in such case (this is default mode if for any reason constraint build fail in such case. It introduced the risk that in case 3rd-party breaking dependency was released it would also start breaking regular PRs, not only the "canary" build. We fix it by downloading constraints locally when they are remote and using them from there. While this is being worked on in astral-sh/uv#2081 and likely to land in uv 0.1.14, it's also a good idea to actually download the constraints and keep them around - this might be handy if you want to later use constraints to install "golden" set of dependencies wihtout necessity to build the right URL - you can always use `${HOME}/constraints.txt`. This PR fixes it and also changes the fallback mechanism to perform the lowest-direct upgrade only in case the constraint build fails, rather than always run the lowest-dirct upgrade even if constraints install works fine - this will make sure that most PRs are using exactly the constraint version of the dependencies (at least the version of constraints that were generated last time when pyproject.toml changed).
With the change to switch to uv, we skipped constraints being used in CI image - in effect all PR were not using constraints, but they were using not constraint dependencues but lowest-direct mode of installation so direct dependencies would not be upgraded in such case, only the transitive ones, so the risk of failure was anyhow small even if someone released a new, breakong dependency. The reason is that `uv` currently does not support installing constraints from URL. We had been silently failing back to the "no-constraints" way in such case (this is default mode if for any reason constraint build fail in such case. It introduced the risk that in case 3rd-party breaking dependency was released it would also start breaking regular PRs, not only the "canary" build. We fix it by downloading constraints locally when they are remote and using them from there. While this is being worked on in astral-sh/uv#2081 and likely to land in uv 0.1.14, it's also a good idea to actually download the constraints and keep them around - this might be handy if you want to later use constraints to install "golden" set of dependencies wihtout necessity to build the right URL - you can always use `${HOME}/constraints.txt`. This PR fixes it and also changes the fallback mechanism to perform the lowest-direct upgrade only in case the constraint build fails, rather than always run the lowest-dirct upgrade even if constraints install works fine - this will make sure that most PRs are using exactly the constraint version of the dependencies (at least the version of constraints that were generated last time when pyproject.toml changed).
With the change to switch to uv, we skipped constraints being used in CI image - in effect all PR were not using constraints, but they were using not constraint dependencues but lowest-direct mode of installation so direct dependencies would not be upgraded in such case, only the transitive ones, so the risk of failure was anyhow small even if someone released a new, breakong dependency. The reason is that `uv` currently does not support installing constraints from URL. We had been silently failing back to the "no-constraints" way in such case (this is default mode if for any reason constraint build fail in such case. It introduced the risk that in case 3rd-party breaking dependency was released it would also start breaking regular PRs, not only the "canary" build. We fix it by downloading constraints locally when they are remote and using them from there. While this is being worked on in astral-sh/uv#2081 and likely to land in uv 0.1.14, it's also a good idea to actually download the constraints and keep them around - this might be handy if you want to later use constraints to install "golden" set of dependencies wihtout necessity to build the right URL - you can always use `${HOME}/constraints.txt`. This PR fixes it and also changes the fallback mechanism to perform the lowest-direct upgrade only in case the constraint build fails, rather than always run the lowest-dirct upgrade even if constraints install works fine - this will make sure that most PRs are using exactly the constraint version of the dependencies (at least the version of constraints that were generated last time when pyproject.toml changed).
crates/requirements-txt/src/lib.rs
Outdated
@@ -386,13 +390,14 @@ impl RequirementsTxt { | |||
end, | |||
} => { | |||
let sub_file = requirements_dir.join(filename); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the join here is fine even if filename
is a URL?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup works really well from my testing. It is basically handled like a relative path starting with the http:
directory. The only sketchy thing I could find for now is that it doesn't survive a round trip through .components()
:
PathBuf::from_iter(PathBuf::from_str("http://test/abc.txt").unwrap().components())
= http:/test/abc.txt
(one /
missing).
@@ -320,24 +321,25 @@ pub struct RequirementsTxt { | |||
impl RequirementsTxt { | |||
/// See module level documentation | |||
#[instrument(skip_all, fields(requirements_txt = requirements_txt.as_ref().as_os_str().to_str()))] | |||
pub fn parse( | |||
pub async fn parse( | |||
requirements_txt: impl AsRef<Path>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the question of using Path
: Part of me feels like we should be using VerbatimUrl
for this (used elsewhere in this crate). VerbatimUrl
can represent both URLs and paths, but it preserves the user-provided representation, which we leverage to ensure that we don't expand environment variables (like secrets) when we write results back out to requirements.txt
. I think we would need a join
method on it, which would perhaps be somewhat awkward... But would you mind giving it a try, and seeing if it fits? Alternatively, we can punt it to another PR -- I would be open to merging without it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to give it a try in a separate PR!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good, thanks! Some comments below, only one blocking.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, one other critical point: how does this work with authentication? Does pip support reading from URLs that require authentication?
We probably need to pass through our RegistryClient
or something similarly-constructed. That would also ensure that this behavior respects the --offline
flag.
Pip seems to ask for interactive input when the url requires auth:
With my current implementation, uv would interpret the "no auth header" message as a package name, which seems dangeous:
I'll try to figure out how to mirror pips behavior, and take a look at the |
this change also causes pyproject.toml files to be excluded from the remote file logic
With the change to switch to uv, we skipped constraints being used in CI image - in effect all PR were not using constraints, but they were using not constraint dependencues but lowest-direct mode of installation so direct dependencies would not be upgraded in such case, only the transitive ones, so the risk of failure was anyhow small even if someone released a new, breakong dependency. The reason is that `uv` currently does not support installing constraints from URL. We had been silently failing back to the "no-constraints" way in such case (this is default mode if for any reason constraint build fail in such case. It introduced the risk that in case 3rd-party breaking dependency was released it would also start breaking regular PRs, not only the "canary" build. We fix it by downloading constraints locally when they are remote and using them from there. While this is being worked on in astral-sh/uv#2081 and likely to land in uv 0.1.14, it's also a good idea to actually download the constraints and keep them around - this might be handy if you want to later use constraints to install "golden" set of dependencies wihtout necessity to build the right URL - you can always use `${HOME}/constraints.txt`. This PR fixes it and also changes the fallback mechanism to perform the lowest-direct upgrade only in case the constraint build fails, rather than always run the lowest-dirct upgrade even if constraints install works fine - this will make sure that most PRs are using exactly the constraint version of the dependencies (at least the version of constraints that were generated last time when pyproject.toml changed).
@charliermarsh I moved the http handling into |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
@jannisko -- I mostly made cosmetic changes, but I did make one behavioral change, which is that I removed |
https://
requirements files (#1332)
06360f3
to
ae476a2
Compare
Thanks a lot @charliermarsh for all the feedback! |
With the change to switch to uv, we skipped constraints being used in CI image - in effect all PR were not using constraints, but they were using not constraint dependencues but lowest-direct mode of installation so direct dependencies would not be upgraded in such case, only the transitive ones, so the risk of failure was anyhow small even if someone released a new, breakong dependency. The reason is that `uv` currently does not support installing constraints from URL. We had been silently failing back to the "no-constraints" way in such case (this is default mode if for any reason constraint build fail in such case. It introduced the risk that in case 3rd-party breaking dependency was released it would also start breaking regular PRs, not only the "canary" build. We fix it by downloading constraints locally when they are remote and using them from there. While this is being worked on in astral-sh/uv#2081 and likely to land in uv 0.1.14, it's also a good idea to actually download the constraints and keep them around - this might be handy if you want to later use constraints to install "golden" set of dependencies wihtout necessity to build the right URL - you can always use `${HOME}/constraints.txt`. This PR fixes it and also changes the fallback mechanism to perform the lowest-direct upgrade only in case the constraint build fails, rather than always run the lowest-dirct upgrade even if constraints install works fine - this will make sure that most PRs are using exactly the constraint version of the dependencies (at least the version of constraints that were generated last time when pyproject.toml changed).
Summary
Allow using http(s) urls for constraints and requirements files handed to the CLI, by handling paths starting with
http://
orhttps://
differently. This allows commands for such as:uv pip install -c https://raw.githubusercontent.com/apache/airflow/constraints-2.8.1/constraints-3.8.txt requests
.closes #1332
Test Plan
Testing install using a
constraints.txt
file hosted on github in the airflow repository:https://github.com/jannisko/uv/blob/fbdc2eba8e5e8fb4160baae495daff8fb48df13f/crates/uv/tests/pip_install.rs#L1440-L1484
Advice Needed
crates/uv-fs/src/lib.rs#read_to_string
). Should I change some naming here so it is obvious that the function is able to dispatch?