From b602356983652e96bedc5a3a1ef76bcd7bb2cc4a Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Sun, 18 Apr 2021 17:26:14 +0100 Subject: [PATCH 1/6] Add support for reading the requirements from pyproject.toml --- dep_checker/__init__.py | 19 +++++++++-------- dep_checker/__main__.py | 45 ++++++++++++++++++++++++++++++++++------- doc-source/usage.rst | 6 ++++++ 3 files changed, 53 insertions(+), 17 deletions(-) diff --git a/dep_checker/__init__.py b/dep_checker/__init__.py index 84b21fe..1f69673 100644 --- a/dep_checker/__init__.py +++ b/dep_checker/__init__.py @@ -39,6 +39,7 @@ from consolekit.terminal_colours import Fore, resolve_color_default from domdf_python_tools.paths import PathPlus, in_directory from domdf_python_tools.typing import PathLike +from packaging.requirements import Requirement from shippinglabel.requirements import read_requirements # this package @@ -315,18 +316,18 @@ def iter_files_to_check(basepath: PathLike, pkg_name: str) -> Iterator[PathPlus] def check_imports( pkg_name: str, - req_file: PathLike = "requirements.txt", + *requirements: Requirement, allowed_unused: Optional[List[str]] = None, colour: Optional[bool] = None, name_mapping: Optional[Dict[str, str]] = None, namespace_packages: Optional[List[str]] = None, work_dir: PathLike = '.', ) -> int: - """ + r""" Check imports for the given package, against the given requirements file. :param pkg_name: - :param req_file: + :param \*requirements: :param allowed_unused: List of requirements which are allowed to be unused in the source code. :default allowed_unused: ``[]`` :param colour: Whether to use coloured output. @@ -346,6 +347,10 @@ def check_imports( * Added the ``name_mapping`` option. * Added the ``work_dir`` option. + + .. versionchanged:: 0.7.0 Replaced the ``req_file`` argument with the ``*requirements`` argument. + Use :func:`shippinglabel.requirements.read_requirements(req_file)[0] ` + to get the original bevhaviour. """ ret = 0 @@ -362,17 +367,11 @@ def check_imports( namespace_packages = NamespacePackages.get(config) work_dir = PathPlus(work_dir) - req_file = PathPlus(req_file) - - if not req_file.is_absolute(): - req_file = work_dir / req_file - - req_file = req_file.abspath() work_dir = work_dir.abspath() checker = DepChecker( pkg_name, - requirements=map(attrgetter("name"), read_requirements(req_file)[0]), + requirements=map(attrgetter("name"), requirements), allowed_unused=allowed_unused, name_mapping=name_mapping, namespace_packages=namespace_packages, diff --git a/dep_checker/__main__.py b/dep_checker/__main__.py index 7c91ad7..14112ab 100644 --- a/dep_checker/__main__.py +++ b/dep_checker/__main__.py @@ -32,11 +32,15 @@ # 3rd party import click +import dom_toml from consolekit import click_command -from consolekit.options import colour_option +from consolekit.options import auto_default_option, colour_option, flag_option from consolekit.utils import abort # this package +from domdf_python_tools.paths import PathPlus +from shippinglabel.requirements import parse_pyproject_dependencies, read_requirements + from dep_checker import check_imports __all__ = ("main", ) @@ -57,12 +61,16 @@ multiple=True, help="Requirements which are allowed to be unused in the source code.", ) -@click.option( +@auto_default_option( "--req-file", type=click.STRING, metavar="FILENAME", - default="requirements.txt", - help="The requirements file.", + help="Parse the requirements from the given requirements file.", + ) +@flag_option( + "-P", "--pyproject", + type=click.STRING, + help="Parse the requirements from 'pyproject.toml'.", ) @click.argument( "pkg-name", @@ -71,10 +79,11 @@ @click_command() def main( pkg_name: str, - req_file: str, allowed_unused: Optional[List[str]], - colour: Optional[bool], + colour: Optional[bool] = None, + req_file: str = "requirements.txt", work_dir: str = '.', + pyproject: bool = False ) -> None: """ Tool to check all requirements are actually required. @@ -83,10 +92,32 @@ def main( if allowed_unused == (): allowed_unused = None + work_dir = PathPlus(work_dir) + + def read_req_file(req_file): + req_file = PathPlus(req_file) + + if not req_file.is_absolute(): + req_file = work_dir / req_file + + return read_requirements(req_file)[0] + + if pyproject: + pyproject_file = work_dir / "pyproject.toml" + dynamic = dom_toml.load(pyproject_file)["project"].get("dynamic", ()) + + if "requirements" in dynamic: + requirements = read_req_file(work_dir / "requirements.txt") + else: + requirements = parse_pyproject_dependencies(pyproject_file, flavour="pep621") + + else: + requirements = read_req_file(req_file) + try: ret = check_imports( pkg_name, - req_file=req_file, + *requirements, allowed_unused=allowed_unused, colour=colour, work_dir=work_dir, diff --git a/doc-source/usage.rst b/doc-source/usage.rst index c4e7453..79ce0e9 100644 --- a/doc-source/usage.rst +++ b/doc-source/usage.rst @@ -109,6 +109,12 @@ Command Line :prog: dep-checker +The :option:`-P / --pyproject <-P>` option takes precedence over the :option:`--req-file` option. + +.. versionchanged:: 0.7.0 + + Added the :option:`-P / --pyproject <-P>` option. + As a ``pre-commit`` hook ---------------------------- From 17aa713e70d3b0f14df0bd0056afa1dec4f078db Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Tue, 6 Jan 2026 17:40:38 +0000 Subject: [PATCH 2/6] Retarget 1.0.0 --- dep_checker/__init__.py | 2 +- doc-source/usage.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dep_checker/__init__.py b/dep_checker/__init__.py index 1f69673..39b9a1b 100644 --- a/dep_checker/__init__.py +++ b/dep_checker/__init__.py @@ -348,7 +348,7 @@ def check_imports( * Added the ``name_mapping`` option. * Added the ``work_dir`` option. - .. versionchanged:: 0.7.0 Replaced the ``req_file`` argument with the ``*requirements`` argument. + .. versionchanged:: 1.0.0 Replaced the ``req_file`` argument with the ``*requirements`` argument. Use :func:`shippinglabel.requirements.read_requirements(req_file)[0] ` to get the original bevhaviour. """ diff --git a/doc-source/usage.rst b/doc-source/usage.rst index 79ce0e9..0b486a4 100644 --- a/doc-source/usage.rst +++ b/doc-source/usage.rst @@ -111,7 +111,7 @@ Command Line The :option:`-P / --pyproject <-P>` option takes precedence over the :option:`--req-file` option. -.. versionchanged:: 0.7.0 +.. versionchanged:: 1.0.0 Added the :option:`-P / --pyproject <-P>` option. From b239a005299b2c1c7f3369266410fb8a864609dc Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Tue, 6 Jan 2026 18:50:53 +0000 Subject: [PATCH 3/6] Fix existing tests. --- dep_checker/__main__.py | 19 +++++++------------ requirements.txt | 1 + tests/test_dep_checker.py | 11 ++++++++--- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/dep_checker/__main__.py b/dep_checker/__main__.py index 14112ab..7cceb48 100644 --- a/dep_checker/__main__.py +++ b/dep_checker/__main__.py @@ -36,11 +36,10 @@ from consolekit import click_command from consolekit.options import auto_default_option, colour_option, flag_option from consolekit.utils import abort - -# this package from domdf_python_tools.paths import PathPlus from shippinglabel.requirements import parse_pyproject_dependencies, read_requirements +# this package from dep_checker import check_imports __all__ = ("main", ) @@ -67,11 +66,7 @@ metavar="FILENAME", help="Parse the requirements from the given requirements file.", ) -@flag_option( - "-P", "--pyproject", - type=click.STRING, - help="Parse the requirements from 'pyproject.toml'.", - ) +@flag_option("-P", "--pyproject", help="Parse the requirements from 'pyproject.toml'.", default=False,) @click.argument( "pkg-name", type=click.STRING, @@ -92,22 +87,22 @@ def main( if allowed_unused == (): allowed_unused = None - work_dir = PathPlus(work_dir) + work_dir_p = PathPlus(work_dir) def read_req_file(req_file): req_file = PathPlus(req_file) if not req_file.is_absolute(): - req_file = work_dir / req_file + req_file = work_dir_p / req_file return read_requirements(req_file)[0] if pyproject: - pyproject_file = work_dir / "pyproject.toml" + pyproject_file = work_dir_p / "pyproject.toml" dynamic = dom_toml.load(pyproject_file)["project"].get("dynamic", ()) if "requirements" in dynamic: - requirements = read_req_file(work_dir / "requirements.txt") + requirements = read_req_file(work_dir_p / "requirements.txt") else: requirements = parse_pyproject_dependencies(pyproject_file, flavour="pep621") @@ -120,7 +115,7 @@ def read_req_file(req_file): *requirements, allowed_unused=allowed_unused, colour=colour, - work_dir=work_dir, + work_dir=work_dir_p, ) sys.exit(ret) except FileNotFoundError as e: diff --git a/requirements.txt b/requirements.txt index a1ad829..29ce00f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,4 +4,5 @@ configconfig>=0.4.0 consolekit>=0.4.0 dom-toml>=0.2.0 domdf-python-tools>=3.2.0 +packaging>=25.0 shippinglabel>=0.1.0 diff --git a/tests/test_dep_checker.py b/tests/test_dep_checker.py index 9eab2b8..b6a6cf5 100644 --- a/tests/test_dep_checker.py +++ b/tests/test_dep_checker.py @@ -1,7 +1,8 @@ # stdlib -from typing import Any, Dict +from typing import Any, Dict, List # 3rd party +from packaging.requirements import Requirement import pytest from coincidence import AdvancedDataRegressionFixture from consolekit.testing import CliRunner, Result @@ -22,19 +23,21 @@ def test_check_imports( single_file_project: PathPlus, capsys, + requirements: List[str], advanced_data_regression: AdvancedDataRegressionFixture, ): - assert check_imports("my_project", work_dir=single_file_project, colour=False) == 1 + assert check_imports("my_project", *map(Requirement, requirements), work_dir=single_file_project, colour=False) == 1 advanced_data_regression.check(capsys.readouterr()) def test_check_imports_package( package_project: PathPlus, capsys, + requirements: List[str], advanced_data_regression: AdvancedDataRegressionFixture, ): - assert check_imports("my_project", work_dir=package_project, colour=False) == 1 + assert check_imports("my_project", *map(Requirement, requirements), work_dir=package_project, colour=False) == 1 advanced_data_regression.check(capsys.readouterr()) @@ -96,9 +99,11 @@ def test_with_config( capsys, advanced_data_regression: AdvancedDataRegressionFixture, config: Dict[str, Any], + requirements: List[str], ): assert check_imports( "my_project", + *map(Requirement, requirements), work_dir=single_file_project, colour=False, **config, From 4df3deecb1ff926ebb112908fcc479430031151a Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Tue, 6 Jan 2026 20:13:24 +0000 Subject: [PATCH 4/6] Add tests --- dep_checker/__init__.py | 1 - dep_checker/__main__.py | 36 ++++-- tests/test_dep_checker.py | 24 ++-- tests/test_dep_checker_pyproject.py | 120 ++++++++++++++++++ .../test_dep_checker_pyproject_/test_cli.txt | 12 ++ .../test_cli_dynamic.txt | 15 +++ .../test_cli_package.txt | 12 ++ .../test_cli_package_dynamic.txt | 15 +++ .../test_cli_package_srcdir.txt | 12 ++ 9 files changed, 224 insertions(+), 23 deletions(-) create mode 100644 tests/test_dep_checker_pyproject.py create mode 100644 tests/test_dep_checker_pyproject_/test_cli.txt create mode 100644 tests/test_dep_checker_pyproject_/test_cli_dynamic.txt create mode 100644 tests/test_dep_checker_pyproject_/test_cli_package.txt create mode 100644 tests/test_dep_checker_pyproject_/test_cli_package_dynamic.txt create mode 100644 tests/test_dep_checker_pyproject_/test_cli_package_srcdir.txt diff --git a/dep_checker/__init__.py b/dep_checker/__init__.py index 39b9a1b..6fb87c7 100644 --- a/dep_checker/__init__.py +++ b/dep_checker/__init__.py @@ -40,7 +40,6 @@ from domdf_python_tools.paths import PathPlus, in_directory from domdf_python_tools.typing import PathLike from packaging.requirements import Requirement -from shippinglabel.requirements import read_requirements # this package from dep_checker.config import AllowedUnused, ConfigReader, NameMapping, NamespacePackages diff --git a/dep_checker/__main__.py b/dep_checker/__main__.py index 7cceb48..da450ee 100644 --- a/dep_checker/__main__.py +++ b/dep_checker/__main__.py @@ -28,16 +28,14 @@ # stdlib import sys -from typing import List, Optional +from typing import List, Optional, Set # 3rd party import click import dom_toml from consolekit import click_command -from consolekit.options import auto_default_option, colour_option, flag_option +from consolekit.options import colour_option, flag_option from consolekit.utils import abort -from domdf_python_tools.paths import PathPlus -from shippinglabel.requirements import parse_pyproject_dependencies, read_requirements # this package from dep_checker import check_imports @@ -60,13 +58,18 @@ multiple=True, help="Requirements which are allowed to be unused in the source code.", ) -@auto_default_option( +@click.option( "--req-file", type=click.STRING, metavar="FILENAME", - help="Parse the requirements from the given requirements file.", + help="Parse the requirements from the given requirements file (or pyproject.toml file with --pyproject).", + ) +@flag_option( + "-p", + "--pyproject", + help="Parse the requirements from 'pyproject.toml'.", + default=False, ) -@flag_option("-P", "--pyproject", help="Parse the requirements from 'pyproject.toml'.", default=False,) @click.argument( "pkg-name", type=click.STRING, @@ -76,7 +79,7 @@ def main( pkg_name: str, allowed_unused: Optional[List[str]], colour: Optional[bool] = None, - req_file: str = "requirements.txt", + req_file: Optional[str] = None, work_dir: str = '.', pyproject: bool = False ) -> None: @@ -84,12 +87,17 @@ def main( Tool to check all requirements are actually required. """ + # 3rd party + from domdf_python_tools.paths import PathPlus + from domdf_python_tools.typing import PathLike + from shippinglabel.requirements import ComparableRequirement, parse_pyproject_dependencies, read_requirements + if allowed_unused == (): allowed_unused = None work_dir_p = PathPlus(work_dir) - def read_req_file(req_file): + def read_req_file(req_file: PathLike) -> Set[ComparableRequirement]: req_file = PathPlus(req_file) if not req_file.is_absolute(): @@ -98,15 +106,19 @@ def read_req_file(req_file): return read_requirements(req_file)[0] if pyproject: - pyproject_file = work_dir_p / "pyproject.toml" - dynamic = dom_toml.load(pyproject_file)["project"].get("dynamic", ()) + if req_file is None: + req_file = "pyproject.toml" + dynamic = dom_toml.load(req_file)["project"].get("dynamic", ()) if "requirements" in dynamic: requirements = read_req_file(work_dir_p / "requirements.txt") else: - requirements = parse_pyproject_dependencies(pyproject_file, flavour="pep621") + requirements = parse_pyproject_dependencies(req_file, flavour="pep621") else: + if req_file is None: + req_file = "requirements.txt" + requirements = read_req_file(req_file) try: diff --git a/tests/test_dep_checker.py b/tests/test_dep_checker.py index b6a6cf5..06a55ca 100644 --- a/tests/test_dep_checker.py +++ b/tests/test_dep_checker.py @@ -2,12 +2,12 @@ from typing import Any, Dict, List # 3rd party -from packaging.requirements import Requirement import pytest from coincidence import AdvancedDataRegressionFixture +from coincidence.regressions import AdvancedFileRegressionFixture from consolekit.testing import CliRunner, Result from domdf_python_tools.paths import PathPlus, in_directory -from pytest_regressions.file_regression import FileRegressionFixture +from packaging.requirements import Requirement # this package from dep_checker import ( @@ -26,7 +26,9 @@ def test_check_imports( requirements: List[str], advanced_data_regression: AdvancedDataRegressionFixture, ): - assert check_imports("my_project", *map(Requirement, requirements), work_dir=single_file_project, colour=False) == 1 + assert check_imports( + "my_project", *map(Requirement, requirements), work_dir=single_file_project, colour=False + ) == 1 advanced_data_regression.check(capsys.readouterr()) @@ -37,34 +39,36 @@ def test_check_imports_package( advanced_data_regression: AdvancedDataRegressionFixture, ): - assert check_imports("my_project", *map(Requirement, requirements), work_dir=package_project, colour=False) == 1 + assert check_imports( + "my_project", *map(Requirement, requirements), work_dir=package_project, colour=False + ) == 1 advanced_data_regression.check(capsys.readouterr()) def test_cli( single_file_project: PathPlus, - file_regression: FileRegressionFixture, + advanced_file_regression: AdvancedFileRegressionFixture, ): with in_directory(single_file_project): runner = CliRunner() result: Result = runner.invoke(main, args=["my_project", "--no-colour"]) - result.check_stdout(file_regression) + result.check_stdout(advanced_file_regression) assert result.exit_code == 1 -def test_cli_package(package_project: PathPlus, file_regression: FileRegressionFixture): +def test_cli_package(package_project: PathPlus, advanced_file_regression: AdvancedFileRegressionFixture): with in_directory(package_project): runner = CliRunner() result: Result = runner.invoke(main, args=["my_project", "--no-colour"]) - result.check_stdout(file_regression) + result.check_stdout(advanced_file_regression) assert result.exit_code == 1 -def test_cli_package_srcdir(package_project: PathPlus, file_regression: FileRegressionFixture): +def test_cli_package_srcdir(package_project: PathPlus, advanced_file_regression: AdvancedFileRegressionFixture): (package_project / "my_project").move(package_project / "src" / "my_project") with in_directory(package_project): @@ -74,7 +78,7 @@ def test_cli_package_srcdir(package_project: PathPlus, file_regression: FileRegr args=["my_project", "--no-colour", "--work-dir", "src", "--req-file", "../requirements.txt"], ) - result.check_stdout(file_regression) + result.check_stdout(advanced_file_regression) assert result.exit_code == 1 diff --git a/tests/test_dep_checker_pyproject.py b/tests/test_dep_checker_pyproject.py new file mode 100644 index 0000000..c5a97bd --- /dev/null +++ b/tests/test_dep_checker_pyproject.py @@ -0,0 +1,120 @@ +# stdlib +from typing import List + +# 3rd party +import dom_toml +from coincidence.regressions import AdvancedFileRegressionFixture +from consolekit.testing import CliRunner, Result +from domdf_python_tools.paths import PathPlus, in_directory + +# this package +from dep_checker.__main__ import main + + +def test_cli( + single_file_project: PathPlus, + requirements: List[str], + advanced_file_regression: AdvancedFileRegressionFixture, + ): + + with in_directory(single_file_project): + dom_toml.dump( + {"project": {"name": "foo", "requirements": requirements}}, + single_file_project / "pyproject.toml", + ) + runner = CliRunner() + result: Result = runner.invoke(main, args=["my_project", "--no-colour", "-p"]) + + result.check_stdout(advanced_file_regression) + assert result.exit_code == 1 + + +def test_cli_package( + package_project: PathPlus, + requirements: List[str], + advanced_file_regression: AdvancedFileRegressionFixture + ): + + with in_directory(package_project): + dom_toml.dump( + {"project": {"name": "foo", "requirements": requirements}}, + package_project / "pyproject.toml", + ) + runner = CliRunner() + result: Result = runner.invoke(main, args=["my_project", "--no-colour", "-p"]) + + result.check_stdout(advanced_file_regression) + assert result.exit_code == 1 + + +def test_cli_package_srcdir( + package_project: PathPlus, + requirements: List[str], + advanced_file_regression: AdvancedFileRegressionFixture + ): + (package_project / "my_project").move(package_project / "src" / "my_project") + + with in_directory(package_project): + dom_toml.dump( + {"project": {"name": "foo", "requirements": requirements}}, + package_project / "pyproject.toml", + ) + runner = CliRunner() + result: Result = runner.invoke( + main, + args=["my_project", "--no-colour", "--work-dir", "src", "-p"], + ) + + result.check_stdout(advanced_file_regression) + assert result.exit_code == 1 + + +def test_cli_dynamic( + single_file_project: PathPlus, + advanced_file_regression: AdvancedFileRegressionFixture, + ): + + with in_directory(single_file_project): + dom_toml.dump( + {"project": {"name": "foo", "dynamic": ["requirements"]}}, + single_file_project / "pyproject.toml", + ) + runner = CliRunner() + result: Result = runner.invoke(main, args=["my_project", "--no-colour", "-p"]) + + result.check_stdout(advanced_file_regression) + assert result.exit_code == 1 + + +def test_cli_package_dynamic(package_project: PathPlus, advanced_file_regression: AdvancedFileRegressionFixture): + + with in_directory(package_project): + dom_toml.dump( + {"project": {"name": "foo", "dynamic": ["requirements"]}}, + package_project / "pyproject.toml", + ) + runner = CliRunner() + result: Result = runner.invoke(main, args=["my_project", "--no-colour", "-p"]) + + result.check_stdout(advanced_file_regression) + assert result.exit_code == 1 + + +def test_cli_package_srcdir_dynamic( + package_project: PathPlus, advanced_file_regression: AdvancedFileRegressionFixture + ): + (package_project / "my_project").move(package_project / "src" / "my_project") + + with in_directory(package_project): + dom_toml.dump( + {"project": {"name": "foo", "dynamic": ["requirements"]}}, + package_project / "pyproject.toml", + ) + runner = CliRunner() + result: Result = runner.invoke( + main, + args=["my_project", "--no-colour", "--work-dir", "src", "-p"], + ) + + result.check_stdout(advanced_file_regression) + assert result.exit_code == 1 diff --git a/tests/test_dep_checker_pyproject_/test_cli.txt b/tests/test_dep_checker_pyproject_/test_cli.txt new file mode 100644 index 0000000..442e94e --- /dev/null +++ b/tests/test_dep_checker_pyproject_/test_cli.txt @@ -0,0 +1,12 @@ +✘ pytest imported at my_project.py:5 but not listed as a requirement +✘ chemistry_tools imported at my_project.py:6 but not listed as a requirement +✘ pathlib2 imported at my_project.py:7 but not listed as a requirement +✘ typing_extensions imported at my_project.py:8 but not listed as a requirement +✘ domdf_python_tools imported at my_project.py:9 but not listed as a requirement +✘ consolekit imported at my_project.py:10 but not listed as a requirement +✘ click imported at my_project.py:11 but not listed as a requirement +✘ pandas imported at my_project.py:12 but not listed as a requirement +✘ ruamel imported at my_project.py:13 but not listed as a requirement +✘ Bio imported at my_project.py:15 but not listed as a requirement +✘ configconfig imported at my_project.py:31 but not listed as a requirement +✘ setuptools imported at my_project.py:35 but not listed as a requirement diff --git a/tests/test_dep_checker_pyproject_/test_cli_dynamic.txt b/tests/test_dep_checker_pyproject_/test_cli_dynamic.txt new file mode 100644 index 0000000..0e4e81d --- /dev/null +++ b/tests/test_dep_checker_pyproject_/test_cli_dynamic.txt @@ -0,0 +1,15 @@ +✘ pytest imported at my_project.py:5 but not listed as a requirement +✘ chemistry_tools imported at my_project.py:6 but not listed as a requirement +✘ pathlib2 imported at my_project.py:7 but not listed as a requirement +✘ typing_extensions imported at my_project.py:8 but not listed as a requirement +✘ domdf_python_tools imported at my_project.py:9 but not listed as a requirement +✘ click imported at my_project.py:11 but not listed as a requirement +✘ ruamel imported at my_project.py:13 but not listed as a requirement +✘ Bio imported at my_project.py:15 but not listed as a requirement +✘ configconfig imported at my_project.py:31 but not listed as a requirement +✘ setuptools imported at my_project.py:35 but not listed as a requirement +✘ biopython never imported +✘ coincidence never imported +✔ consolekit imported at my_project.py:10 +✘ numpy never imported +✔ pandas imported at my_project.py:12 diff --git a/tests/test_dep_checker_pyproject_/test_cli_package.txt b/tests/test_dep_checker_pyproject_/test_cli_package.txt new file mode 100644 index 0000000..cb74eac --- /dev/null +++ b/tests/test_dep_checker_pyproject_/test_cli_package.txt @@ -0,0 +1,12 @@ +✘ pytest imported at my_project/__init__.py:5 but not listed as a requirement +✘ chemistry_tools imported at my_project/__init__.py:6 but not listed as a requirement +✘ pathlib2 imported at my_project/__init__.py:7 but not listed as a requirement +✘ typing_extensions imported at my_project/__init__.py:8 but not listed as a requirement +✘ domdf_python_tools imported at my_project/__init__.py:9 but not listed as a requirement +✘ consolekit imported at my_project/__init__.py:10 but not listed as a requirement +✘ click imported at my_project/__init__.py:11 but not listed as a requirement +✘ pandas imported at my_project/__init__.py:12 but not listed as a requirement +✘ ruamel imported at my_project/__init__.py:13 but not listed as a requirement +✘ Bio imported at my_project/__init__.py:15 but not listed as a requirement +✘ configconfig imported at my_project/__init__.py:31 but not listed as a requirement +✘ setuptools imported at my_project/__init__.py:35 but not listed as a requirement diff --git a/tests/test_dep_checker_pyproject_/test_cli_package_dynamic.txt b/tests/test_dep_checker_pyproject_/test_cli_package_dynamic.txt new file mode 100644 index 0000000..f46e57d --- /dev/null +++ b/tests/test_dep_checker_pyproject_/test_cli_package_dynamic.txt @@ -0,0 +1,15 @@ +✘ pytest imported at my_project/__init__.py:5 but not listed as a requirement +✘ chemistry_tools imported at my_project/__init__.py:6 but not listed as a requirement +✘ pathlib2 imported at my_project/__init__.py:7 but not listed as a requirement +✘ typing_extensions imported at my_project/__init__.py:8 but not listed as a requirement +✘ domdf_python_tools imported at my_project/__init__.py:9 but not listed as a requirement +✘ click imported at my_project/__init__.py:11 but not listed as a requirement +✘ ruamel imported at my_project/__init__.py:13 but not listed as a requirement +✘ Bio imported at my_project/__init__.py:15 but not listed as a requirement +✘ configconfig imported at my_project/__init__.py:31 but not listed as a requirement +✘ setuptools imported at my_project/__init__.py:35 but not listed as a requirement +✘ biopython never imported +✘ coincidence never imported +✔ consolekit imported at my_project/__init__.py:10 +✘ numpy never imported +✔ pandas imported at my_project/__init__.py:12 diff --git a/tests/test_dep_checker_pyproject_/test_cli_package_srcdir.txt b/tests/test_dep_checker_pyproject_/test_cli_package_srcdir.txt new file mode 100644 index 0000000..cb74eac --- /dev/null +++ b/tests/test_dep_checker_pyproject_/test_cli_package_srcdir.txt @@ -0,0 +1,12 @@ +✘ pytest imported at my_project/__init__.py:5 but not listed as a requirement +✘ chemistry_tools imported at my_project/__init__.py:6 but not listed as a requirement +✘ pathlib2 imported at my_project/__init__.py:7 but not listed as a requirement +✘ typing_extensions imported at my_project/__init__.py:8 but not listed as a requirement +✘ domdf_python_tools imported at my_project/__init__.py:9 but not listed as a requirement +✘ consolekit imported at my_project/__init__.py:10 but not listed as a requirement +✘ click imported at my_project/__init__.py:11 but not listed as a requirement +✘ pandas imported at my_project/__init__.py:12 but not listed as a requirement +✘ ruamel imported at my_project/__init__.py:13 but not listed as a requirement +✘ Bio imported at my_project/__init__.py:15 but not listed as a requirement +✘ configconfig imported at my_project/__init__.py:31 but not listed as a requirement +✘ setuptools imported at my_project/__init__.py:35 but not listed as a requirement From 3ba22d0f2c27350a435004ae7aea12da2a8421f4 Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Tue, 6 Jan 2026 21:48:34 +0000 Subject: [PATCH 5/6] requirements.txt read for dynamic dependencies should be relative. --- dep_checker/__main__.py | 5 ++--- .../test_cli_package_srcdir_dynamic.txt | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 tests/test_dep_checker_pyproject_/test_cli_package_srcdir_dynamic.txt diff --git a/dep_checker/__main__.py b/dep_checker/__main__.py index da450ee..80ea330 100644 --- a/dep_checker/__main__.py +++ b/dep_checker/__main__.py @@ -88,8 +88,7 @@ def main( """ # 3rd party - from domdf_python_tools.paths import PathPlus - from domdf_python_tools.typing import PathLike + from domdf_python_tools.paths import PathLike, PathPlus from shippinglabel.requirements import ComparableRequirement, parse_pyproject_dependencies, read_requirements if allowed_unused == (): @@ -111,7 +110,7 @@ def read_req_file(req_file: PathLike) -> Set[ComparableRequirement]: dynamic = dom_toml.load(req_file)["project"].get("dynamic", ()) if "requirements" in dynamic: - requirements = read_req_file(work_dir_p / "requirements.txt") + requirements = read_requirements("requirements.txt")[0] else: requirements = parse_pyproject_dependencies(req_file, flavour="pep621") diff --git a/tests/test_dep_checker_pyproject_/test_cli_package_srcdir_dynamic.txt b/tests/test_dep_checker_pyproject_/test_cli_package_srcdir_dynamic.txt new file mode 100644 index 0000000..f46e57d --- /dev/null +++ b/tests/test_dep_checker_pyproject_/test_cli_package_srcdir_dynamic.txt @@ -0,0 +1,15 @@ +✘ pytest imported at my_project/__init__.py:5 but not listed as a requirement +✘ chemistry_tools imported at my_project/__init__.py:6 but not listed as a requirement +✘ pathlib2 imported at my_project/__init__.py:7 but not listed as a requirement +✘ typing_extensions imported at my_project/__init__.py:8 but not listed as a requirement +✘ domdf_python_tools imported at my_project/__init__.py:9 but not listed as a requirement +✘ click imported at my_project/__init__.py:11 but not listed as a requirement +✘ ruamel imported at my_project/__init__.py:13 but not listed as a requirement +✘ Bio imported at my_project/__init__.py:15 but not listed as a requirement +✘ configconfig imported at my_project/__init__.py:31 but not listed as a requirement +✘ setuptools imported at my_project/__init__.py:35 but not listed as a requirement +✘ biopython never imported +✘ coincidence never imported +✔ consolekit imported at my_project/__init__.py:10 +✘ numpy never imported +✔ pandas imported at my_project/__init__.py:12 From 2a1ced11c564888b7317fdfa46a01930d665b4ae Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Tue, 6 Jan 2026 21:51:09 +0000 Subject: [PATCH 6/6] Reduce packaging requirement. --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 29ce00f..54a2f9e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,5 +4,5 @@ configconfig>=0.4.0 consolekit>=0.4.0 dom-toml>=0.2.0 domdf-python-tools>=3.2.0 -packaging>=25.0 +packaging>=20.9 shippinglabel>=0.1.0