From 708ced23a7abd33612554c34849cc773bc6feec9 Mon Sep 17 00:00:00 2001 From: Alon Ohana Date: Wed, 23 Apr 2025 17:51:49 +0300 Subject: [PATCH 1/6] Added an option to export to requirements.txt without markers --- src/poetry_plugin_export/command.py | 9 +++++ src/poetry_plugin_export/exporter.py | 9 ++++- tests/test_exporter.py | 58 ++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/poetry_plugin_export/command.py b/src/poetry_plugin_export/command.py index 51db1e7..dfa5597 100644 --- a/src/poetry_plugin_export/command.py +++ b/src/poetry_plugin_export/command.py @@ -21,6 +21,10 @@ class ExportCommand(GroupCommand): description = "Exports the lock file to alternative formats." options = [ # noqa: RUF012 + option("without-markers", + None, + "Include markers in the exported file (default - True).", + flag=True), option( "format", "f", @@ -146,6 +150,10 @@ def handle(self) -> int: ) return 1 + without_markers = False + if self.option("without-markers"): + without_markers = self.option("without-markers") + groups = ( self.poetry.package.dependency_group_names(include_optional=True) if self.option("all-groups") @@ -153,6 +161,7 @@ def handle(self) -> int: ) exporter = Exporter(self.poetry, self.io) + exporter.with_markers(not without_markers) exporter.only_groups(list(groups)) exporter.with_extras(list(extras)) exporter.with_hashes(not self.option("without-hashes")) diff --git a/src/poetry_plugin_export/exporter.py b/src/poetry_plugin_export/exporter.py index 35922a5..321086b 100644 --- a/src/poetry_plugin_export/exporter.py +++ b/src/poetry_plugin_export/exporter.py @@ -45,6 +45,7 @@ def __init__(self, poetry: Poetry, io: IO) -> None: self._with_hashes = True self._with_credentials = False self._with_urls = True + self._with_markers = True self._extras: Collection[NormalizedName] = () self._groups: Iterable[str] = [MAIN_GROUP] @@ -72,6 +73,12 @@ def with_hashes(self, with_hashes: bool = True) -> Exporter: return self + def with_markers(self, with_markers: bool = True) -> Exporter: + # This is a no-op for now, but we can implement it in the future + # if needed. + self._with_markers = with_markers + return self + def with_credentials(self, with_credentials: bool = True) -> Exporter: self._with_credentials = with_credentials @@ -153,7 +160,7 @@ def _export_generic_txt( if not is_direct_remote_reference and ";" in requirement: markers = requirement.split(";", 1)[1].strip() - if markers: + if markers and self._with_markers: line += f" ; {markers}" if ( diff --git a/tests/test_exporter.py b/tests/test_exporter.py index d2fbb74..11b364f 100644 --- a/tests/test_exporter.py +++ b/tests/test_exporter.py @@ -519,6 +519,64 @@ def test_exporter_can_export_requirements_txt_with_nested_packages_and_markers( assert expected == {} +@pytest.mark.parametrize("lock_version", ["2.1"]) +def test_exporter_with_no_markers_flag(tmp_path: Path, poetry: Poetry, lock_version: str) -> None: + lock_data = { + "package": [ + { + "name": "greenlet", + "version": "3.2.1", + "optional": False, + "python-versions": ">=3.9", + "markers": 'python_version < "3.14" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32")', + }, + { + "name": "typing-extensions", + "version": "4.13.2", + "optional": False, + "python-versions": ">=3.8", + }, + { + "name": "sqlalchemy", + "version": "2.0.40", + "optional": False, + "python-versions": ">=3.7", + "dependencies": { + "greenlet": { + "version": ">=1", + "markers": 'python_version < "3.14" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32")' + }, + "typing-extensions": ">=4.6.0" + }, + } + ], + "metadata": { + "lock-version": lock_version, + "files": { + "greenlet": [], + "typing-extensions": [], + "sqlalchemy": [] + } + }, + } + + fix_lock_data(lock_data) + poetry.locker.mock_lock_data(lock_data) # type: ignore[attr-defined] + + exporter = Exporter(poetry, NullIO()) + exporter.with_markers(False) + exporter.export("requirements.txt", tmp_path, "requirements.txt") + + with open(tmp_path / "requirements.txt") as f: + lines = set(f.read().strip().splitlines()) + + expected = { + 'greenlet==3.2.1', + 'sqlalchemy==2.0.40', + 'typing-extensions==4.13.2', + } + + assert lines == expected @pytest.mark.parametrize( ["dev", "lines"], From ba1994f979ce332a3e1e1afed536f8b19b6026c1 Mon Sep 17 00:00:00 2001 From: Alon Ohana Date: Wed, 23 Apr 2025 18:00:54 +0300 Subject: [PATCH 2/6] Reordered --without-markers flag to appear last for consistency with internal argument handling. --- src/poetry_plugin_export/command.py | 14 ++++++-------- src/poetry_plugin_export/exporter.py | 20 ++++++++------------ 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/poetry_plugin_export/command.py b/src/poetry_plugin_export/command.py index dfa5597..7035c54 100644 --- a/src/poetry_plugin_export/command.py +++ b/src/poetry_plugin_export/command.py @@ -4,14 +4,12 @@ from typing import TYPE_CHECKING from cleo.helpers import option -from packaging.utils import NormalizedName -from packaging.utils import canonicalize_name +from packaging.utils import NormalizedName, canonicalize_name from poetry.console.commands.group_command import GroupCommand from poetry.core.packages.dependency_group import MAIN_GROUP from poetry_plugin_export.exporter import Exporter - if TYPE_CHECKING: from collections.abc import Iterable @@ -21,10 +19,6 @@ class ExportCommand(GroupCommand): description = "Exports the lock file to alternative formats." options = [ # noqa: RUF012 - option("without-markers", - None, - "Include markers in the exported file (default - True).", - flag=True), option( "format", "f", @@ -79,6 +73,10 @@ class ExportCommand(GroupCommand): ), option("all-extras", None, "Include all sets of extra dependencies."), option("with-credentials", None, "Include credentials for extra indices."), + option("without-markers", + None, + "Include markers in the exported file (default - True).", + flag=True), ] @property @@ -161,12 +159,12 @@ def handle(self) -> int: ) exporter = Exporter(self.poetry, self.io) - exporter.with_markers(not without_markers) exporter.only_groups(list(groups)) exporter.with_extras(list(extras)) exporter.with_hashes(not self.option("without-hashes")) exporter.with_credentials(self.option("with-credentials")) exporter.with_urls(not self.option("without-urls")) + exporter.with_markers(not without_markers) exporter.export(fmt, Path.cwd(), output or self.io) return 0 diff --git a/src/poetry_plugin_export/exporter.py b/src/poetry_plugin_export/exporter.py index 321086b..c6e1598 100644 --- a/src/poetry_plugin_export/exporter.py +++ b/src/poetry_plugin_export/exporter.py @@ -1,7 +1,6 @@ from __future__ import annotations import urllib.parse - from functools import partialmethod from typing import TYPE_CHECKING @@ -11,13 +10,11 @@ from poetry.core.version.markers import parse_marker from poetry.repositories.http_repository import HTTPRepository -from poetry_plugin_export.walker import get_project_dependency_packages -from poetry_plugin_export.walker import get_project_dependency_packages2 - +from poetry_plugin_export.walker import (get_project_dependency_packages, + get_project_dependency_packages2) if TYPE_CHECKING: - from collections.abc import Collection - from collections.abc import Iterable + from collections.abc import Collection, Iterable from pathlib import Path from typing import ClassVar @@ -73,17 +70,16 @@ def with_hashes(self, with_hashes: bool = True) -> Exporter: return self - def with_markers(self, with_markers: bool = True) -> Exporter: - # This is a no-op for now, but we can implement it in the future - # if needed. - self._with_markers = with_markers - return self - def with_credentials(self, with_credentials: bool = True) -> Exporter: self._with_credentials = with_credentials return self + def with_markers(self, with_markers: bool = True) -> Exporter: + self._with_markers = with_markers + + return self + def export(self, fmt: str, cwd: Path, output: IO | str) -> None: if not self.is_format_supported(fmt): raise ValueError(f"Invalid export format: {fmt}") From 939d84621359b4379fd91dc924b702c266084a26 Mon Sep 17 00:00:00 2001 From: Alon Ohana Date: Wed, 23 Apr 2025 18:10:52 +0300 Subject: [PATCH 3/6] formatting --- src/poetry_plugin_export/command.py | 14 +++++++++----- src/poetry_plugin_export/exporter.py | 9 ++++++--- tests/test_exporter.py | 24 ++++++++++++------------ 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/poetry_plugin_export/command.py b/src/poetry_plugin_export/command.py index 7035c54..b136525 100644 --- a/src/poetry_plugin_export/command.py +++ b/src/poetry_plugin_export/command.py @@ -4,12 +4,14 @@ from typing import TYPE_CHECKING from cleo.helpers import option -from packaging.utils import NormalizedName, canonicalize_name +from packaging.utils import NormalizedName +from packaging.utils import canonicalize_name from poetry.console.commands.group_command import GroupCommand from poetry.core.packages.dependency_group import MAIN_GROUP from poetry_plugin_export.exporter import Exporter + if TYPE_CHECKING: from collections.abc import Iterable @@ -73,10 +75,12 @@ class ExportCommand(GroupCommand): ), option("all-extras", None, "Include all sets of extra dependencies."), option("with-credentials", None, "Include credentials for extra indices."), - option("without-markers", - None, - "Include markers in the exported file (default - True).", - flag=True), + option( + "without-markers", + None, + "Include markers in the exported file (default - True).", + flag=True, + ), ] @property diff --git a/src/poetry_plugin_export/exporter.py b/src/poetry_plugin_export/exporter.py index c6e1598..1a028a7 100644 --- a/src/poetry_plugin_export/exporter.py +++ b/src/poetry_plugin_export/exporter.py @@ -1,6 +1,7 @@ from __future__ import annotations import urllib.parse + from functools import partialmethod from typing import TYPE_CHECKING @@ -10,11 +11,13 @@ from poetry.core.version.markers import parse_marker from poetry.repositories.http_repository import HTTPRepository -from poetry_plugin_export.walker import (get_project_dependency_packages, - get_project_dependency_packages2) +from poetry_plugin_export.walker import get_project_dependency_packages +from poetry_plugin_export.walker import get_project_dependency_packages2 + if TYPE_CHECKING: - from collections.abc import Collection, Iterable + from collections.abc import Collection + from collections.abc import Iterable from pathlib import Path from typing import ClassVar diff --git a/tests/test_exporter.py b/tests/test_exporter.py index 11b364f..945ec45 100644 --- a/tests/test_exporter.py +++ b/tests/test_exporter.py @@ -519,8 +519,11 @@ def test_exporter_can_export_requirements_txt_with_nested_packages_and_markers( assert expected == {} + @pytest.mark.parametrize("lock_version", ["2.1"]) -def test_exporter_with_no_markers_flag(tmp_path: Path, poetry: Poetry, lock_version: str) -> None: +def test_exporter_with_no_markers_flag( + tmp_path: Path, poetry: Poetry, lock_version: str +) -> None: lock_data = { "package": [ { @@ -544,19 +547,15 @@ def test_exporter_with_no_markers_flag(tmp_path: Path, poetry: Poetry, lock_vers "dependencies": { "greenlet": { "version": ">=1", - "markers": 'python_version < "3.14" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32")' + "markers": 'python_version < "3.14" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32")', }, - "typing-extensions": ">=4.6.0" + "typing-extensions": ">=4.6.0", }, - } + }, ], "metadata": { "lock-version": lock_version, - "files": { - "greenlet": [], - "typing-extensions": [], - "sqlalchemy": [] - } + "files": {"greenlet": [], "typing-extensions": [], "sqlalchemy": []}, }, } @@ -571,13 +570,14 @@ def test_exporter_with_no_markers_flag(tmp_path: Path, poetry: Poetry, lock_vers lines = set(f.read().strip().splitlines()) expected = { - 'greenlet==3.2.1', - 'sqlalchemy==2.0.40', - 'typing-extensions==4.13.2', + "greenlet==3.2.1", + "sqlalchemy==2.0.40", + "typing-extensions==4.13.2", } assert lines == expected + @pytest.mark.parametrize( ["dev", "lines"], [ From 4536d9626313bc934dbe60d870e3f83ce97cbe88 Mon Sep 17 00:00:00 2001 From: Alon Ohana Date: Wed, 23 Apr 2025 18:28:57 +0300 Subject: [PATCH 4/6] Fixed terminology --- README.md | 1 + src/poetry_plugin_export/command.py | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2e15a25..90b19db 100644 --- a/README.md +++ b/README.md @@ -61,3 +61,4 @@ poetry export -f requirements.txt --output requirements.txt * `--all-groups`: Include all dependency groups. * `--without-hashes`: Exclude hashes from the exported file. * `--with-credentials`: Include credentials for extra indices. +* `--without-markers`: Exclude markers in the exported file. diff --git a/src/poetry_plugin_export/command.py b/src/poetry_plugin_export/command.py index b136525..33dbb8d 100644 --- a/src/poetry_plugin_export/command.py +++ b/src/poetry_plugin_export/command.py @@ -4,14 +4,12 @@ from typing import TYPE_CHECKING from cleo.helpers import option -from packaging.utils import NormalizedName -from packaging.utils import canonicalize_name +from packaging.utils import NormalizedName, canonicalize_name from poetry.console.commands.group_command import GroupCommand from poetry.core.packages.dependency_group import MAIN_GROUP from poetry_plugin_export.exporter import Exporter - if TYPE_CHECKING: from collections.abc import Iterable @@ -78,7 +76,7 @@ class ExportCommand(GroupCommand): option( "without-markers", None, - "Include markers in the exported file (default - True).", + "Exclude markers in the exported file.", flag=True, ), ] From 353e09dba9ca97c82da1b6e67ae72fbb582ad442 Mon Sep 17 00:00:00 2001 From: Alon Ohana Date: Wed, 23 Apr 2025 18:32:00 +0300 Subject: [PATCH 5/6] Formatting --- src/poetry_plugin_export/command.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/poetry_plugin_export/command.py b/src/poetry_plugin_export/command.py index 33dbb8d..f0c342f 100644 --- a/src/poetry_plugin_export/command.py +++ b/src/poetry_plugin_export/command.py @@ -4,12 +4,14 @@ from typing import TYPE_CHECKING from cleo.helpers import option -from packaging.utils import NormalizedName, canonicalize_name +from packaging.utils import NormalizedName +from packaging.utils import canonicalize_name from poetry.console.commands.group_command import GroupCommand from poetry.core.packages.dependency_group import MAIN_GROUP from poetry_plugin_export.exporter import Exporter + if TYPE_CHECKING: from collections.abc import Iterable From bf0f05ab4426b759831477770e21cb06b8b8ce90 Mon Sep 17 00:00:00 2001 From: Alon Ohana Date: Wed, 23 Apr 2025 18:35:11 +0300 Subject: [PATCH 6/6] Trigger format