Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 24 additions & 7 deletions src/fromager/packagesettings/_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from pydantic import AnyUrl, Field
from pydantic_core import core_schema

# from ._resolver import SourceResolver
from ._resolver import SourceResolver
from ._typedefs import (
MODEL_CONFIG,
BuildDirectory,
Expand Down Expand Up @@ -324,9 +324,11 @@ class VariantInfo(pydantic.BaseModel):
pre_built: bool = False
"""Use pre-built wheel from index server?"""

# TODO
# source: SourceResolver | None
# """Source resolver and downloader"""
source: SourceResolver | None = None
"""Source resolver and downloader

.. versionadded:: 0.86
"""


class GitOptions(pydantic.BaseModel):
Expand All @@ -336,6 +338,7 @@ class GitOptions(pydantic.BaseModel):

submodules: False
submodule_paths: []
remove_dot_git: False
"""

model_config = MODEL_CONFIG
Expand All @@ -358,6 +361,18 @@ class GitOptions(pydantic.BaseModel):
- ["vendor/lib1", "vendor/lib2"]
"""

remove_dot_git: bool = False
"""Remove ``.git`` directory after cloning?

When True, the ``.git`` directory is removed from the cloned source
tree so it does not end up in the built sdist. Defaults to False
to preserve backward compatibility with existing ``req.url`` git
clones that rely on ``.git`` for version detection (e.g. via
setuptools-scm).

.. versionadded:: 0.85
Comment thread
smoparth marked this conversation as resolved.
"""


_DictStrAny = dict[str, typing.Any]

Expand Down Expand Up @@ -452,9 +467,11 @@ class PackageSettings(pydantic.BaseModel):
project_override: ProjectOverride = Field(default_factory=ProjectOverride)
"""Patch project settings"""

# TODO
# source: SourceResolver | None
# """Source resolver and downloader"""
source: SourceResolver | None = None
"""Source resolver and downloader

.. versionadded:: 0.86
"""

variants: Mapping[Variant, VariantInfo] = Field(default_factory=dict)
"""Variant configuration"""
Expand Down
13 changes: 13 additions & 0 deletions src/fromager/packagesettings/_pbi.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

if typing.TYPE_CHECKING:
from .. import build_environment
from ._resolver import SourceResolver
from ._settings import Settings

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -176,6 +177,18 @@ def pre_built(self) -> bool:
return vi.pre_built
return False

@property
def source_resolver(self) -> SourceResolver | None:
"""Effective source resolver for this package and variant.

Returns the variant-level ``source`` override if set, otherwise
the package-level ``source``, or ``None`` when neither is configured.
"""
vi = self._ps.variants.get(self._variant)
if vi is not None and vi.source is not None:
return vi.source
return self._ps.source

@property
def wheel_server_url(self) -> str | None:
"""Alternative package index for pre-build wheel"""
Expand Down
48 changes: 35 additions & 13 deletions src/fromager/packagesettings/_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ class AbstractResolver(pydantic.BaseModel):
provider: str

def resolver_provider(
self, ctx: context.WorkContext, req_type: requirements_file.RequirementType
self,
ctx: context.WorkContext,
req_type: requirements_file.RequirementType | None = None,
) -> resolver.BaseProvider:
raise NotImplementedError

Expand Down Expand Up @@ -88,7 +90,9 @@ class PyPISDistResolver(AbstractPyPIResolver):
build_sdist: typing.ClassVar[BuildSDist | None] = BuildSDist.tarball

def resolver_provider(
self, ctx: context.WorkContext, req_type: requirements_file.RequirementType
self,
ctx: context.WorkContext,
req_type: requirements_file.RequirementType | None = None,
) -> resolver.PyPIProvider:
return resolver.PyPIProvider(
include_sdists=True,
Expand Down Expand Up @@ -123,7 +127,9 @@ class PyPIPrebuiltResolver(AbstractPyPIResolver):
build_sdist: typing.ClassVar[BuildSDist | None] = None

def resolver_provider(
self, ctx: context.WorkContext, req_type: requirements_file.RequirementType
self,
ctx: context.WorkContext,
req_type: requirements_file.RequirementType | None = None,
) -> resolver.PyPIProvider:
return resolver.PyPIProvider(
include_sdists=False,
Expand Down Expand Up @@ -177,7 +183,9 @@ def validate_download_url(cls, value: pydantic.HttpUrl) -> pydantic.HttpUrl:
return value

def resolver_provider(
self, ctx: context.WorkContext, req_type: requirements_file.RequirementType
self,
ctx: context.WorkContext,
req_type: requirements_file.RequirementType | None = None,
) -> resolver.PyPIProvider:
return resolver.PyPIProvider(
include_sdists=True,
Expand Down Expand Up @@ -245,7 +253,9 @@ def validate_tag(cls, value: str) -> str:
return value

def resolver_provider(
self, ctx: context.WorkContext, req_type: requirements_file.RequirementType
self,
ctx: context.WorkContext,
req_type: requirements_file.RequirementType | None = None,
) -> resolver.PyPIProvider:
download_url = f"git+{self.clone_url}@refs/tags/{self.tag}"
return resolver.PyPIProvider(
Expand Down Expand Up @@ -342,7 +352,7 @@ def _github_provider(
self,
*,
ctx: context.WorkContext,
req_type: requirements_file.RequirementType,
req_type: requirements_file.RequirementType | None = None,
override_download_url: str | None = None,
) -> resolver.GitHubTagProvider:
if self.project_url.host != "github.com":
Expand All @@ -366,7 +376,7 @@ def _gitlab_provider(
self,
*,
ctx: context.WorkContext,
req_type: requirements_file.RequirementType,
req_type: requirements_file.RequirementType | None = None,
override_download_url: str | None = None,
) -> resolver.GitLabTagProvider:
if not self.project_url.path:
Expand Down Expand Up @@ -398,7 +408,9 @@ class GitHubTagDownloadResolver(AbstractGitSourceResolver):
provider: typing.Literal["github-tag-download"]

def resolver_provider(
self, ctx: context.WorkContext, req_type: requirements_file.RequirementType
self,
ctx: context.WorkContext,
req_type: requirements_file.RequirementType | None = None,
) -> resolver.GitHubTagProvider:
return self._github_provider(
ctx=ctx,
Expand All @@ -423,7 +435,9 @@ class GitHubTagCloneResolver(AbstractGitSourceResolver):
provider: typing.Literal["github-tag-git"]

def resolver_provider(
self, ctx: context.WorkContext, req_type: requirements_file.RequirementType
self,
ctx: context.WorkContext,
req_type: requirements_file.RequirementType | None = None,
) -> resolver.GitHubTagProvider:
return self._github_provider(
ctx=ctx,
Expand All @@ -448,7 +462,9 @@ class GitLabTagDownloadResolver(AbstractGitSourceResolver):
provider: typing.Literal["gitlab-tag-download"]

def resolver_provider(
self, ctx: context.WorkContext, req_type: requirements_file.RequirementType
self,
ctx: context.WorkContext,
req_type: requirements_file.RequirementType | None = None,
) -> resolver.GitLabTagProvider:
return self._gitlab_provider(
ctx=ctx,
Expand All @@ -473,7 +489,9 @@ class GitLabTagCloneResolver(AbstractGitSourceResolver):
provider: typing.Literal["gitlab-tag-git"]

def resolver_provider(
self, ctx: context.WorkContext, req_type: requirements_file.RequirementType
self,
ctx: context.WorkContext,
req_type: requirements_file.RequirementType | None = None,
) -> resolver.GitLabTagProvider:
return self._gitlab_provider(
ctx=ctx,
Expand All @@ -488,7 +506,9 @@ class NotAvailableResolver(AbstractResolver):
provider: typing.Literal["not-available"]

def resolver_provider(
self, ctx: context.WorkContext, req_type: requirements_file.RequirementType
self,
ctx: context.WorkContext,
req_type: requirements_file.RequirementType | None = None,
) -> resolver.BaseProvider:
raise ValueError("package is not available")

Expand All @@ -499,7 +519,9 @@ class HookResolver(AbstractResolver):
provider: typing.Literal["hook"]

def resolver_provider(
self, ctx: context.WorkContext, req_type: requirements_file.RequirementType
self,
ctx: context.WorkContext,
req_type: requirements_file.RequirementType | None = None,
) -> resolver.BaseProvider:
# TODO
raise NotImplementedError("Hook resolver needs a hook")
Expand Down
45 changes: 24 additions & 21 deletions src/fromager/resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,19 +90,28 @@ def resolve(

Returns (url, version) tuple for the highest matching version.
"""
# Create the (reusable) resolver.
provider = overrides.find_and_invoke(
req.name,
"get_resolver_provider",
default_resolver_provider,
ctx=ctx,
req=req,
include_sdists=include_sdists,
include_wheels=include_wheels,
sdist_server_url=sdist_server_url,
req_type=req_type,
ignore_platform=ignore_platform,
)
pbi = ctx.package_build_info(req)
source = pbi.source_resolver
if source is not None and source.provider != "hook":
logger.info(
"%s: using source resolver provider %r",
req.name,
source.provider,
)
provider = source.resolver_provider(ctx, req_type)
else:
provider = overrides.find_and_invoke(
req.name,
"get_resolver_provider",
default_resolver_provider,
ctx=ctx,
req=req,
include_sdists=include_sdists,
include_wheels=include_wheels,
sdist_server_url=sdist_server_url,
req_type=req_type,
ignore_platform=ignore_platform,
)
provider.cooldown = resolve_package_cooldown(ctx, req, req_type=req_type)
max_age_cutoff = _compute_max_age_cutoff(ctx)
results = find_all_matching_from_provider(
Expand All @@ -119,14 +128,8 @@ def default_resolver_provider(
include_wheels: bool,
req_type: RequirementType | None = None,
ignore_platform: bool = False,
) -> (
PyPIProvider
| GenericProvider
| GitHubTagProvider
| GitLabTagProvider
| VersionMapProvider
):
"""Lookup resolver provider to resolve package versions"""
) -> BaseProvider:
"""Lookup resolver provider to resolve package versions."""
return PyPIProvider(
include_sdists=include_sdists,
include_wheels=include_wheels,
Expand Down
Loading
Loading