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

modularize handle_requirement #453

Merged
Merged
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
557 changes: 557 additions & 0 deletions src/fromager/bootstrapper.py

Large diffs are not rendered by default.

12 changes: 4 additions & 8 deletions src/fromager/commands/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
from packaging.requirements import Requirement

from .. import (
bootstrapper,
clickext,
context,
dependency_graph,
progress,
requirements_file,
resolver,
sdist,
server,
sources,
wheels,
Expand Down Expand Up @@ -133,14 +133,10 @@ def bootstrap(
)

with progress.progress_context(total=len(to_build)) as progressbar:
bt = bootstrapper.Bootstrapper(wkctx, progressbar, prev_graph)

for req in to_build:
sdist.handle_requirement(
wkctx,
req,
req_type=requirements_file.RequirementType.TOP_LEVEL,
progressbar=progressbar,
prev_graph=prev_graph,
)
bt.bootstrap(req, requirements_file.RequirementType.TOP_LEVEL)
progressbar.update()

# If we put pre-built wheels in the downloads directory, we should
Expand Down
67 changes: 0 additions & 67 deletions src/fromager/context.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import collections
import json
import logging
import os
import pathlib
import typing
from urllib.parse import urlparse

from packaging.requirements import Requirement
Expand Down Expand Up @@ -71,26 +68,10 @@ def __init__(
self.network_isolation = network_isolation
self.settings_dir = settings_dir

self._build_order_filename = self.work_dir / "build-order.json"
self._constraints_filename = self.work_dir / "constraints.txt"

# Push items onto the stack as we start to resolve their
# dependencies so at the end we have a list of items that need to
# be built in order.
self._build_stack: list[typing.Any] = []
self._build_requirements: set[tuple[NormalizedName, str]] = set()
self.all_edges: BuildRequirements = collections.defaultdict(list)
self.dependency_graph = dependency_graph.DependencyGraph()

# Track requirements we've seen before so we don't resolve the
# same dependencies over and over and so we can break cycles in
# the dependency list. The key is the requirements spec, rather
# than the package, in case we do have multiple rules for the same
# package.
self._seen_requirements: set[tuple[NormalizedName, tuple[str, ...], str]] = (
set()
)

@property
def pip_wheel_server_args(self) -> list[str]:
args = ["--index-url", self.wheel_server_url]
Expand All @@ -105,54 +86,6 @@ def pip_constraint_args(self) -> list[str]:
return []
return ["--constraint", os.fspath(self.input_constraints_file)]

def _resolved_key(
self, req: Requirement, version: Version
) -> tuple[NormalizedName, tuple[str, ...], str]:
return (canonicalize_name(req.name), tuple(sorted(req.extras)), str(version))

def mark_as_seen(self, req: Requirement, version: Version) -> None:
key = self._resolved_key(req, version)
logger.debug(f"{req.name}: remembering seen sdist {key}")
self._seen_requirements.add(key)

def has_been_seen(self, req: Requirement, version: Version) -> bool:
return self._resolved_key(req, version) in self._seen_requirements

def add_to_build_order(
self,
req: Requirement,
version: Version,
source_url: str,
source_url_type: str,
prebuilt: bool = False,
constraint: Requirement | None = None,
) -> None:
# We only care if this version of this package has been built,
# and don't want to trigger building it twice. The "extras"
# value, included in the _resolved_key() output, can confuse
# that so we ignore itand build our own key using just the
# name and version.
key = (canonicalize_name(req.name), str(version))
if key in self._build_requirements:
return
logger.info(f"{req.name}: adding {key} to build order")
self._build_requirements.add(key)
info = {
"req": str(req),
"constraint": str(constraint) if constraint else "",
"dist": canonicalize_name(req.name),
"version": str(version),
"prebuilt": prebuilt,
"source_url": source_url,
"source_url_type": source_url_type,
}
self._build_stack.append(info)
with open(self._build_order_filename, "w") as f:
# Set default=str because the why value includes
# Requirement and Version instances that can't be
# converted to JSON without help.
json.dump(self._build_stack, f, indent=2, default=str)

def write_to_graph_to_file(self):
with open(self.work_dir / "graph.json", "w") as f:
self.dependency_graph.serialize(f)
Expand Down
6 changes: 6 additions & 0 deletions src/fromager/requirements_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ class RequirementType(StrEnum):
BUILD_SDIST = "build-sdist"


class SourceType(StrEnum):
PREBUILT = "prebuilt"
SDIST = "sdist"
OVERRIDE = "override"


def parse_requirements_file(
req_file: pathlib.Path,
) -> typing.Iterable[str]:
Expand Down
Loading
Loading