-
Notifications
You must be signed in to change notification settings - Fork 738
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 conflicting URL in separate forks #4435
Conversation
CodSpeed Performance ReportMerging #4435 will improve performances by 23.65%Comparing Summary
Benchmarks breakdown
|
b1c9cfd
to
714df58
Compare
4f77bc4
to
4965708
Compare
714df58
to
aaa0acb
Compare
I caused this error during development and having the name of the task on it is helpful for debugging. Split out from #4435
I have to add yet another indentation level to the prerelease-available check in `PubGrubReportFormatter::hints` for #4435, so i've broken the code into methods and decreased indentation in this split out refactoring-only change.
I have to add yet another indentation level to the prerelease-available check in `PubGrubReportFormatter::hints` for #4435, so i've broken the code into methods and decreased indentation in this split out refactoring-only change.
3a08323
to
8386382
Compare
4965708
to
8fb9c69
Compare
In the last PR (#4430), we flatten the requirements. In the next PR (#4435), we want to pass `Url` around next to `PubGrubPackage` and `Range<Version>` to keep track of which `Requirement`s added a url across forking. This PR is a refactoring split out from #4435 that rolls the dependency conversion into a single iterator and introduces a new `PubGrubDependency` struct as abstraction over `(PubGrubPackage, Range<Version>)` (or `(PubGrubPackage, Range<Version>, VerbatimParsedUrl)` in the next PR), and it removes the now unnecessary `PubGrubDependencies` abstraction.
In the last PR (#4430), we flatten the requirements. In the next PR (#4435), we want to pass `Url` around next to `PubGrubPackage` and `Range<Version>` to keep track of which `Requirement`s added a url across forking. This PR is a refactoring split out from #4435 that rolls the dependency conversion into a single iterator and introduces a new `PubGrubDependency` struct as abstraction over `(PubGrubPackage, Range<Version>)` (or `(PubGrubPackage, Range<Version>, VerbatimParsedUrl)` in the next PR), and it removes the now unnecessary `PubGrubDependencies` abstraction.
61e1fcc
to
0a33469
Compare
0a33469
to
01883ea
Compare
// since we weren't sure whether it might also be a URL requirement when | ||
// transforming the requirements. For that case, we do another request here | ||
// (idempotent due to caching). | ||
self.request_package(&state.next, url, &request_sink)?; |
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.
Is this only necessary if url
is None
?
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 guess that's the majority of the time anyway.
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.
We need it if fork_urls
return None
and Urls
return something, that is the case when it's ambiguous. I didn't add that check specifically because request_package
already checks if the request was previously registered
Whenever we encounter an override URL, that takes precedence over everything else. We also only allow only a single URL per package from overrides, not supporting splitting on overrides. Does that make it clearer?
Yes, i think we have to make the same changes for them too. |
In the last PR (#4430), we flatten the requirements. In the next PR (#4435), we want to pass `Url` around next to `PubGrubPackage` and `Range<Version>` to keep track of which `Requirement`s added a url across forking. This PR is a refactoring split out from #4435 that rolls the dependency conversion into a single iterator and introduces a new `PubGrubDependency` struct as abstraction over `(PubGrubPackage, Range<Version>)` (or `(PubGrubPackage, Range<Version>, VerbatimParsedUrl)` in the next PR), and it removes the now unnecessary `PubGrubDependencies` abstraction.
8362f3b
to
9b7e47c
Compare
30f4c2f
to
0101939
Compare
In the last PR (#4430), we flatten the requirements. In the next PR (#4435), we want to pass `Url` around next to `PubGrubPackage` and `Range<Version>` to keep track of which `Requirement`s added a url across forking. This PR is a refactoring split out from #4435 that rolls the dependency conversion into a single iterator and introduces a new `PubGrubDependency` struct as abstraction over `(PubGrubPackage, Range<Version>)` (or `(PubGrubPackage, Range<Version>, VerbatimParsedUrl)` in the next PR), and it removes the now unnecessary `PubGrubDependencies` abstraction.
9b7e47c
to
c75b822
Compare
In the last PR (#4430), we flatten the requirements. In the next PR (#4435), we want to pass `Url` around next to `PubGrubPackage` and `Range<Version>` to keep track of which `Requirement`s added a url across forking. This PR is a refactoring split out from #4435 that rolls the dependency conversion into a single iterator and introduces a new `PubGrubDependency` struct as abstraction over `(PubGrubPackage, Range<Version>)` (or `(PubGrubPackage, Range<Version>, VerbatimParsedUrl)` in the next PR), and it removes the now unnecessary `PubGrubDependencies` abstraction.
d21ab02
to
cb32b21
Compare
`ResolverState::choose_version` had become huge, with an odd match due to the url handling from #4435. This refactoring breaks it into `choose_version`, `choose_version_registry` and `choose_version_url`. No functional changes.
`ResolverState::choose_version` had become huge, with an odd match due to the url handling from #4435. This refactoring breaks it into `choose_version`, `choose_version_registry` and `choose_version_url`. No functional changes.
`ResolverState::choose_version` had become huge, with an odd match due to the url handling from #4435. This refactoring breaks it into `choose_version`, `choose_version_registry` and `choose_version_url`. No functional changes.
`ResolverState::choose_version` had become huge, with an odd match due to the url handling from #4435. This refactoring breaks it into `choose_version`, `choose_version_registry` and `choose_version_url`. No functional changes.
## Summary Currently, the `Locals` type relies on there being a single local version for a given package. With marker expressions this may not be true, a similar problem to #4435. This changes the `Locals` type to `ForkLocals`, which tracks locals for a given fork. Local versions are now tracked on `PubGrubRequirement` before forking. Resolves #4580.
Downstack PR: #4481
Introduction
We support forking the dependency resolution to support conflicting registry requirements for different platforms, say on package range is required for an older python version while a newer is required for newer python versions, or dependencies that are different per platform. We need to extend this support to direct URL requirements.
This did not work because
Urls
was built on the assumption that there is a single allowed URL per package. We collect all allowed URL ahead of resolution by following direct URL dependencies (including path dependencies) transitively, i.e. a registry distribution can't require a URL.The same package can have Registry and URL requirements
Consider the following two cases:
requirements.in:
pyproject.toml:
In the first case, we want the URL to override the registry dependency, in the second case we want to fork and have one branch use the registry and the other the URL. We have to know about this in
PubGrubRequirement::from_registry_requirement
, but we only fork after the current method.Consider the following case too:
a:
b:
When we convert the requirements of
a
, we can't know the url ofc
yet. The solution is to remove theUrl
fromPubGrubPackage
: TheUrl
is redundant withPackageName
, there can be only one url per package name per fork. We now do the following: We track the urls from requirements inPubGrubDependency
. After forking, we calladd_package_version_dependencies
where we apply override URLs, check if the URL is allowed and check if the url is unique in this fork. When we request a distribution, we ask the fork urls for the real URL. Since we prioritize url dependencies over registry dependencies and skip packages withUrls
entries in pre-visiting, we know that when fetching a package, we know if it has a url or not.URL conflicts
pyproject.toml (invalid):
On the fork state, we keep
ForkUrls
that check for conflicts after forking, rejecting the third case because we added two packages of the same name with different URLs.We need to flatten out the requirements before transformation into pubgrub requirements to get the full list of other requirements which may contain a URL, which was changed in a previous PR: #4430.
Complex Example
a:
b:
b1:
b2:
b3:
In this example, all packages are url requirements (directory requirements) and the root package is
a
. We first split ona
,b
being in each split. In the first fork, we reachb1
, the fork URLs are empty, we insert the iniconfig 1.1.1 URL, and then we skip overb2
andb3
since the mark is disjoint with the fork markers. In the second fork, we skip overb1
, visitb2
, insert the iniconfig 2.0.0 URL into the again empty fork URLs, then visitb3
and try to insert the iniconfig 1.1.0 URL. At this point we find a conflict for the iniconfig URL and error.Closing
The git tests are slow, but they make the best example for different URL types i could find.
Part of #3927. This PR does not handle
Locals
or pre-releases yet.