diff --git a/requirements.txt b/requirements.txt index 005fcae..058ca3a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,8 @@ consolekit>=1.2.1 dom-toml>=0.4.0 domdf-python-tools>=2.9.1 handy-archives>=0.1.0 -mkrecipe>=0.3.0 +mkrecipe>=0.9.0 +packaging>=20.9 pyproject-parser>=0.3.0 shippinglabel>=0.15.0 shippinglabel-conda>=0.1.0 diff --git a/whey_conda/__init__.py b/whey_conda/__init__.py index a437327..032061b 100644 --- a/whey_conda/__init__.py +++ b/whey_conda/__init__.py @@ -46,6 +46,7 @@ from domdf_python_tools.paths import PathPlus from domdf_python_tools.typing import PathLike from domdf_python_tools.words import word_join +from mkrecipe import filter_reqs_by_py_version, filter_reqs_with_markers from mkrecipe.config import MkrecipeParser from pyproject_parser.classes import _NormalisedName from shippinglabel.checksum import get_record_entry @@ -327,7 +328,7 @@ def get_runtime_requirements(self) -> List[ComparableRequirement]: Returns a list of the project's runtime requirements. """ - extras: List[Union[ComparableRequirement, str]] = [] + extras: List[Union[str, ComparableRequirement]] = [] if self.config["conda-extras"] == "all": extras.extend(chain.from_iterable(self.config["optional-dependencies"].values())) @@ -341,14 +342,20 @@ def get_runtime_requirements(self) -> List[ComparableRequirement]: # TODO: handle extras from the dependencies. Lookup the requirements in the wheel metadata. # Perhaps wait until exposed in PyPI API - all_requirements = prepare_requirements(chain(self.config["dependencies"], extra_requirements)) + all_requirements: List[ComparableRequirement] = list( + filter_reqs_with_markers(self.config, chain(self.config["dependencies"], extra_requirements)) + ) + all_requirements = filter_reqs_by_py_version(self.config, all_requirements) self._echo_if_v( f"Checking dependencies against the following channels: " f"{word_join(self.config['conda-channels'], use_repr=True)}" ) - all_requirements = validate_requirements(all_requirements, self.config["conda-channels"]) + all_requirements = validate_requirements( + prepare_requirements(all_requirements), + self.config["conda-channels"], + ) requirements_entries = [req for req in all_requirements if req and req != "numpy"] diff --git a/whey_conda/config.py b/whey_conda/config.py index c2d4e1b..03f22ca 100644 --- a/whey_conda/config.py +++ b/whey_conda/config.py @@ -5,7 +5,7 @@ Configuration for ``whey-conda``. """ # -# Copyright © 2021 Dominic Davis-Foster +# Copyright © 2021-2024 Dominic Davis-Foster # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -31,6 +31,7 @@ # 3rd party from dom_toml.parser import TOML_TYPES, AbstractConfigParser, BadConfigError, construct_path +from packaging.version import Version from typing_extensions import Literal __all__ = ("WheyCondaParser", ) @@ -40,10 +41,16 @@ class WheyCondaParser(AbstractConfigParser): """ Parser for the ``[tool.whey-conda]`` table from ``pyproject.toml``. - .. autosummary-widths:: 7/16 + .. autosummary-widths:: 6/16 """ - defaults = {"conda-description": "%s", "conda-extras": "none", "conda-channels": ("conda-forge", )} + defaults = { + "conda-description": "%s", + "conda-extras": "none", + "conda-channels": ("conda-forge", ), + "min-python-version": None, + "max-python-version": None + } table_name = ("tool", "whey-conda") @@ -124,7 +131,7 @@ def parse_conda_extras( extras = config["conda-extras"] - path_elements = [*self.table_name, "conda-extras"] # pylint: disable=use-tuple-over-list + path_elements = (*self.table_name, "conda-extras") if isinstance(extras, str): extras_lower = extras.lower() @@ -143,6 +150,36 @@ def parse_conda_extras( return extras + def parse_min_python_version(self, config: Dict[str, TOML_TYPES]) -> int: + """ + Parse the ``min-python-version`` key, giving the minimum Python 3.x version to consider requirements for. + + :param config: The unparsed TOML config for the ``[tool.whey-conda]`` table. + + :rtype: + + .. versionadded:: 0.3.0 + """ + + v = Version(str(config["min-python-version"])) + assert v.major == 3 + return v.minor + + def parse_max_python_version(self, config: Dict[str, TOML_TYPES]) -> int: + """ + Parse the ``max-python-version`` key, giving the maximum Python 3.x version to consider requirements for. + + :param config: The unparsed TOML config for the ``[tool.whey-conda]`` table. + + :rtype: + + .. versionadded:: 0.3.0 + """ + + v = Version(str(config["max-python-version"])) + assert v.major == 3 + return v.minor + @property def keys(self) -> List[str]: """ @@ -153,6 +190,8 @@ def keys(self) -> List[str]: "conda-description", "conda-channels", "conda-extras", + "min-python-version", + "max-python-version", ] def parse(