diff --git a/news/190.feature b/news/190.feature new file mode 100644 index 0000000000000000000000000000000000000000..b2876af0ca88937eb0a3aa296eab98100e4fd57f --- /dev/null +++ b/news/190.feature @@ -0,0 +1 @@ +Provide an option to export requirements from pyproject.toml diff --git a/pdm/cli/commands/export.py b/pdm/cli/commands/export.py index 6d01086878c68484c6af27347a39433a9e2cf7c5..adf8fec424d701634ddb36e4767a42c92f876c75 100644 --- a/pdm/cli/commands/export.py +++ b/pdm/cli/commands/export.py @@ -32,18 +32,35 @@ class Command(BaseCommand): "--output", help="Write output to the given file, or print to stdout if not given", ) + parser.add_argument( + "-p", + "--pyproject", + action="store_true", + help="Read the list of packages from pyproject.toml", + ) def handle(self, project: Project, options: argparse.Namespace) -> None: candidates = [] + if options.pyproject: + options.hashes = False if options.default: # Don't include self candidate - temp = project.get_locked_candidates() - temp.pop(project.meta.name, None) + if options.pyproject: + temp = project.dependencies + else: + temp = project.get_locked_candidates() + temp.pop(project.meta.name, None) candidates.extend(temp.values()) if options.dev: - candidates.extend(project.get_locked_candidates("dev").values()) + if options.pyproject: + candidates.extend(project.dev_dependencies.values()) + else: + candidates.extend(project.get_locked_candidates("dev").values()) for section in options.sections: - candidates.extend(project.get_locked_candidates(section).values()) + if options.pyproject: + candidates.extend(project.get_dependencies(section).values()) + else: + candidates.extend(project.get_locked_candidates(section).values()) content = FORMATS[options.format].export(project, candidates, options) if options.output: Path(options.output).write_text(content) diff --git a/pdm/formats/requirements.py b/pdm/formats/requirements.py index 37c230c8eab420dab9e877204074086b6fe605a6..a0fb74342d791fd138cf2884503f2ea6f7b1a979 100644 --- a/pdm/formats/requirements.py +++ b/pdm/formats/requirements.py @@ -100,7 +100,7 @@ def convert(project, filename): def export(project, candidates, options): lines = [] for candidate in candidates: - req = candidate.req.as_line() + req = getattr(candidate, "req", candidate).as_line() lines.append(req) if options.hashes and candidate.hashes: for item in candidate.hashes.values(): diff --git a/tests/cli/test_cli.py b/tests/cli/test_cli.py index b8d661b3ae0f0728da688582cb4eb4e1b3153e15..a1e4ed647820ca378b031a07bc5a8b4f77ce6864 100644 --- a/tests/cli/test_cli.py +++ b/tests/cli/test_cli.py @@ -261,6 +261,7 @@ def test_export_to_requirements_txt(invoke, fixture_project): project = fixture_project("demo-package") requirements_txt = project.root / "requirements.txt" requirements_no_hashes = project.root / "requirements_simple.txt" + requirements_pyproject = project.root / "requirements.ini" result = invoke(["export"], obj=project) assert result.exit_code == 0 @@ -270,6 +271,10 @@ def test_export_to_requirements_txt(invoke, fixture_project): assert result.exit_code == 0 assert result.output.strip() == requirements_no_hashes.read_text().strip() + result = invoke(["export", "--pyproject"], obj=project) + assert result.exit_code == 0 + assert result.output.strip() == requirements_pyproject.read_text().strip() + result = invoke( ["export", "-o", str(project.root / "requirements_output.txt")], obj=project ) diff --git a/tests/fixtures/projects/demo-package/requirements.ini b/tests/fixtures/projects/demo-package/requirements.ini new file mode 100644 index 0000000000000000000000000000000000000000..03bd533fdee46ec2fc8a29b836fb9060fdc0dd4a --- /dev/null +++ b/tests/fixtures/projects/demo-package/requirements.ini @@ -0,0 +1,2 @@ +flask +--extra-index-url https://test.pypi.org/simple