-
Notifications
You must be signed in to change notification settings - Fork 53
feat(settings): add version-specific prebuilt wheel configuration #1308
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
base: main
Are you sure you want to change the base?
Changes from all commits
976f889
f1d8bc3
fd3d8df
5a169d5
cc6e590
9c3cab8
075ad4f
e8e9fdf
2933651
6d482bf
4a114eb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,17 +3,67 @@ | |
| import logging | ||
| import typing | ||
|
|
||
| from packaging.requirements import Requirement | ||
| from packaging.version import Version | ||
|
|
||
| from .. import resolver, sources, wheels | ||
| from ..requirements_file import RequirementType | ||
| from ._phase import Phase | ||
| from ._prepare_source import PrepareSource | ||
| from ._types import BootstrapPhase | ||
|
|
||
| if typing.TYPE_CHECKING: | ||
| from .. import context | ||
| from ._bootstrapper import Bootstrapper | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| def _re_resolve_url( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function is the most important part of PR and has no test coverage. Can we add tests for (1) re-resolution when version-specific
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added 7 tests in TestReResolveUrl covering: prebuilt success, source success, ExceptionGroup failure, empty source results, wheel_server_url mismatch triggering re-resolution, no re-resolution when settings match, and fallback on failure. |
||
| ctx: context.WorkContext, | ||
| req: Requirement, | ||
| req_type: RequirementType, | ||
| resolved_version: Version, | ||
| pre_built: bool, | ||
| cache_wheel_server_url: str | None, | ||
| ) -> str | None: | ||
| """Re-resolve the download URL when version-specific pre_built differs. | ||
|
|
||
| Returns the new URL or ``None`` if re-resolution fails. | ||
| """ | ||
| pinned_req = Requirement(f"{req.name}=={resolved_version}") | ||
| if pre_built: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can raise an unhandled Can we wrap the prebuilt resolution in a try/except block and return
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wrapped The caller already handles None by falling back to the original URL with a warning. |
||
| wheel_server_urls = wheels.get_wheel_server_urls( | ||
| ctx, | ||
| req, | ||
| cache_wheel_server_url=cache_wheel_server_url, | ||
| version=resolved_version, | ||
| ) | ||
| try: | ||
| url, _ = wheels.resolve_prebuilt_wheel( | ||
| ctx=ctx, | ||
| req=pinned_req, | ||
| wheel_server_urls=wheel_server_urls, | ||
| req_type=req_type, | ||
| ) | ||
| except ExceptionGroup: | ||
| return None | ||
| return str(url) | ||
| else: | ||
| pbi = ctx.package_build_info(req) | ||
| sdist_server = pbi.resolver_sdist_server_url(resolver.PYPI_SERVER_URL) | ||
| provider = sources.get_source_provider( | ||
| ctx=ctx, | ||
| req=pinned_req, | ||
| sdist_server_url=sdist_server, | ||
| req_type=req_type, | ||
| ) | ||
| results = resolver.find_all_matching_from_provider(provider, pinned_req) | ||
| if results: | ||
| return str(results[0][0]) | ||
| return None | ||
|
|
||
|
|
||
| class Start(Phase): | ||
| """Record a resolved requirement in the dependency graph and deduplicate. | ||
|
|
||
|
|
@@ -44,7 +94,46 @@ def run(self, bt: Bootstrapper) -> list[Phase]: | |
| assert wi.resolved_version is not None | ||
| assert wi.source_url is not None | ||
|
|
||
| # Add to graph (skip TOP_LEVEL, already added in _resolve_and_add_top_level) | ||
| wi.build_sdist_only = bt.sdist_only and not wi.is_build_requirement_context() | ||
|
|
||
| # Must set pbi_pre_built before constructing PrepareSource so that | ||
| # PrepareSource.background_work() immediately sees the correct value. | ||
| pbi = bt.ctx.package_build_info(wi.req) | ||
| wi.pbi_pre_built = pbi.is_pre_built(wi.resolved_version) | ||
| wi.exclusive_build = pbi.exclusive_build | ||
|
|
||
| # Re-resolve URL before graph insertion so the graph stores the | ||
| # final URL, and before the seen-check so duplicate parents still | ||
| # get their edge recorded with the correct URL. | ||
| version_url = pbi.get_wheel_server_url(wi.resolved_version) | ||
| variant_url = pbi.wheel_server_url | ||
| needs_re_resolve = wi.pbi_pre_built != pbi.pre_built or ( | ||
| wi.pbi_pre_built and version_url != variant_url | ||
| ) | ||
| if needs_re_resolve: | ||
| logger.info( | ||
| f"{wi.req} {wi.resolved_version}: version-specific override " | ||
| f"(pre_built={wi.pbi_pre_built}, url={version_url}) differs " | ||
| f"from variant default, re-resolving URL" | ||
| ) | ||
| new_url = _re_resolve_url( | ||
| bt.ctx, | ||
| wi.req, | ||
| wi.req_type, | ||
| wi.resolved_version, | ||
| wi.pbi_pre_built, | ||
| bt.cache_wheel_server_url, | ||
| ) | ||
| if new_url is not None: | ||
| wi.source_url = new_url | ||
| else: | ||
| logger.warning( | ||
| f"{wi.req} {wi.resolved_version}: could not re-resolve URL " | ||
| f"for pre_built={wi.pbi_pre_built}, using original" | ||
| ) | ||
|
|
||
| # Add to graph after URL finalization but before the seen-check | ||
| # so every parent-to-dep edge is recorded with the correct URL. | ||
| if wi.req_type != RequirementType.TOP_LEVEL: | ||
| bt.add_to_graph( | ||
| wi.req, | ||
|
|
@@ -54,8 +143,6 @@ def run(self, bt: Bootstrapper) -> list[Phase]: | |
| wi.parent, | ||
| ) | ||
|
|
||
| wi.build_sdist_only = bt.sdist_only and not wi.is_build_requirement_context() | ||
|
|
||
| if bt.has_been_seen(wi.req, wi.resolved_version, wi.build_sdist_only): | ||
| logger.debug( | ||
| f"redundant {wi.req_type} dependency {wi.req} " | ||
|
|
@@ -69,9 +156,4 @@ def run(self, bt: Bootstrapper) -> list[Phase]: | |
| f"new {wi.req_type} dependency {wi.req} resolves to {wi.resolved_version}" | ||
| ) | ||
|
|
||
| # Must set pbi_pre_built before constructing PrepareSource so that | ||
| # PrepareSource.background_work() immediately sees the correct value. | ||
| pbi = bt.ctx.package_build_info(wi.req) | ||
| wi.pbi_pre_built = pbi.pre_built | ||
| wi.exclusive_build = pbi.exclusive_build | ||
| return [PrepareSource(wi)] | ||
Uh oh!
There was an error while loading. Please reload this page.