Skip to content

Commit

Permalink
Constrain all extras for min-deps job
Browse files Browse the repository at this point in the history
  • Loading branch information
flying-sheep committed Nov 14, 2024
1 parent 0146f1a commit d3a2d51
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 34 deletions.
107 changes: 74 additions & 33 deletions ci/scripts/min-deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import sys
from collections import deque
from contextlib import ExitStack
from functools import cached_property
from pathlib import Path
from typing import TYPE_CHECKING

Expand All @@ -25,6 +26,8 @@

if TYPE_CHECKING:
from collections.abc import Generator, Iterable, Sequence
from collections.abc import Set as AbstractSet
from typing import Any, Self


def min_dep(req: Requirement) -> Requirement:
Expand Down Expand Up @@ -77,48 +80,86 @@ def extract_min_deps(


class Args(argparse.Namespace):
path: Path
"""\
Parse a pyproject.toml file and output a list of minimum dependencies.
Output is optimized for `[uv] pip install` (see `-o`/`--output` for details).
"""

_path: Path
output: Path | None
extras: list[str]
_extras: list[str]
_all_extras: bool

@classmethod
def parse(cls, argv: Sequence[str] | None = None) -> Self:
return cls.parser().parse_args(argv, cls())

@classmethod
def parser(cls) -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
prog="min-deps",
description=cls.__doc__,
usage="pip install `python min-deps.py pyproject.toml`",
)
parser.add_argument(
"_path",
metavar="pyproject.toml",
type=Path,
help="Path to pyproject.toml to parse minimum dependencies from",
)
parser.add_argument(
"--extras",
dest="_extras",
metavar="EXTRA",
type=str,
nargs="*",
default=(),
help="extras to install",
)
parser.add_argument(
"--all-extras",
dest="_all_extras",
action="store_true",
help="get all extras",
)
parser.add_argument(
*("--output", "-o"),
metavar="FILE",
type=Path,
default=None,
help=(
"output file (default: stdout). "
"Without this option, output is space-separated for direct passing to `pip install`. "
"With this option, output written to a file newline-separated file usable as `requirements.txt` or `constraints.txt`."
),
)
return parser

@cached_property
def pyproject(self) -> dict[str, Any]:
return tomllib.loads(self._path.read_text())

@cached_property
def extras(self) -> AbstractSet[str]:
if self._extras:
if self._all_extras:
sys.exit("Cannot specify both --extras and --all-extras")
return dict.fromkeys(self._extras).keys()
if not self._all_extras:
return set()
return self.pyproject["project"]["optional-dependencies"].keys()


def main(argv: Sequence[str] | None = None) -> None:
parser = argparse.ArgumentParser(
prog="min-deps",
description=(
"Parse a pyproject.toml file and output a list of minimum dependencies. "
"Output is optimized for `[uv] pip install` (see `-o`/`--output` for details)."
),
usage="pip install `python min-deps.py pyproject.toml`",
)
parser.add_argument(
"path", type=Path, help="pyproject.toml to parse minimum dependencies from"
)
parser.add_argument(
"--extras", type=str, nargs="*", default=(), help="extras to install"
)
parser.add_argument(
*("--output", "-o"),
type=Path,
default=None,
help=(
"output file (default: stdout). "
"Without this option, output is space-separated for direct passing to `pip install`. "
"With this option, output written to a file newline-separated file usable as `requirements.txt` or `constraints.txt`."
),
)

args = parser.parse_args(argv, Args())

pyproject = tomllib.loads(args.path.read_text())
args = Args.parse(argv)

project_name = pyproject["project"]["name"]
project_name = args.pyproject["project"]["name"]
deps = [
*map(Requirement, pyproject["project"]["dependencies"]),
*map(Requirement, args.pyproject["project"]["dependencies"]),
*(Requirement(f"{project_name}[{extra}]") for extra in args.extras),
]

min_deps = extract_min_deps(deps, pyproject=pyproject)
min_deps = extract_min_deps(deps, pyproject=args.pyproject)

sep = "\n" if args.output else " "
with ExitStack() as stack:
Expand Down
2 changes: 1 addition & 1 deletion hatch.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ overrides.matrix.deps.env-vars = [
{ if = ["min"], key = "UV_CONSTRAINT", value = "ci/scanpy-min-deps.txt" },
]
overrides.matrix.deps.pre-install-commands = [
{ if = ["min"], value = "uv run ci/scripts/min-deps.py pyproject.toml -o ci/scanpy-min-deps.txt" },
{ if = ["min"], value = "uv run ci/scripts/min-deps.py pyproject.toml --all-extras -o ci/scanpy-min-deps.txt" },
]
overrides.matrix.deps.python = [
{ if = ["min"], value = "3.10" },
Expand Down

0 comments on commit d3a2d51

Please sign in to comment.