Commit e95a05c9 by Sébastien Eustace Committed by GitHub

Improve the export command (#1277)

* Improve the export command

* Update documentation
parent 93e562ec
...@@ -437,10 +437,13 @@ poetry export -f requirements.txt > requirements.txt ...@@ -437,10 +437,13 @@ poetry export -f requirements.txt > requirements.txt
### Options ### Options
* `--format (-f)`: the format to export to. Currently, only * `--format (-f)`: The format to export to. Currently, only
`requirements.txt` is supported. `requirements.txt` is supported.
* `--output (-o)`: the name of the output file. If omitted, print to standard * `--output (-o)`: The name of the output file. If omitted, print to standard
output. output.
* `--dev`: Include development dependencies.
* `--without-hashes`: Exclude hashes from the exported file.
* `--with-credentials`: Include credentials for extra indices.
## env ## env
......
...@@ -14,6 +14,7 @@ class ExportCommand(Command): ...@@ -14,6 +14,7 @@ class ExportCommand(Command):
option("output", "o", "The name of the output file.", flag=False), option("output", "o", "The name of the output file.", flag=False),
option("without-hashes", None, "Exclude hashes from the exported file."), option("without-hashes", None, "Exclude hashes from the exported file."),
option("dev", None, "Include development dependencies."), option("dev", None, "Include development dependencies."),
option("with-credentials", None, "Include credentials for extra indices."),
] ]
def handle(self): def handle(self):
...@@ -47,11 +48,12 @@ class ExportCommand(Command): ...@@ -47,11 +48,12 @@ class ExportCommand(Command):
"</warning>" "</warning>"
) )
exporter = Exporter(self.poetry.locker) exporter = Exporter(self.poetry)
exporter.export( exporter.export(
fmt, fmt,
self.poetry.file.parent, self.poetry.file.parent,
output or self.io, output or self.io,
with_hashes=not self.option("without-hashes"), with_hashes=not self.option("without-hashes"),
dev=self.option("dev"), dev=self.option("dev"),
with_credentials=self.option("with-credentials"),
) )
...@@ -15,6 +15,7 @@ from .constraints import parse_constraint as parse_generic_constraint ...@@ -15,6 +15,7 @@ from .constraints import parse_constraint as parse_generic_constraint
from .constraints.constraint import Constraint from .constraints.constraint import Constraint
from .constraints.multi_constraint import MultiConstraint from .constraints.multi_constraint import MultiConstraint
from .constraints.union_constraint import UnionConstraint from .constraints.union_constraint import UnionConstraint
from .utils.utils import convert_markers
class Dependency(object): class Dependency(object):
...@@ -188,6 +189,7 @@ class Dependency(object): ...@@ -188,6 +189,7 @@ class Dependency(object):
requirement = self.base_pep_508_name requirement = self.base_pep_508_name
markers = [] markers = []
has_extras = False
if not self.marker.is_any(): if not self.marker.is_any():
marker = self.marker marker = self.marker
if not with_extras: if not with_extras:
...@@ -195,6 +197,8 @@ class Dependency(object): ...@@ -195,6 +197,8 @@ class Dependency(object):
if not marker.is_empty(): if not marker.is_empty():
markers.append(str(marker)) markers.append(str(marker))
has_extras = "extra" in convert_markers(marker)
else: else:
# Python marker # Python marker
if self.python_versions != "*": if self.python_versions != "*":
...@@ -205,7 +209,7 @@ class Dependency(object): ...@@ -205,7 +209,7 @@ class Dependency(object):
) )
in_extras = " || ".join(self._in_extras) in_extras = " || ".join(self._in_extras)
if in_extras and with_extras: if in_extras and with_extras and not has_extras:
markers.append( markers.append(
self._create_nested_marker("extra", parse_generic_constraint(in_extras)) self._create_nested_marker("extra", parse_generic_constraint(in_extras))
) )
......
from typing import Optional from typing import Union
from clikit.api.io import IO from clikit.api.io import IO
from poetry.packages.locker import Locker from poetry.packages.directory_dependency import DirectoryDependency
from poetry.packages.file_dependency import FileDependency
from poetry.packages.url_dependency import URLDependency
from poetry.packages.vcs_dependency import VCSDependency
from poetry.poetry import Poetry
from poetry.utils._compat import Path from poetry.utils._compat import Path
from poetry.utils._compat import decode from poetry.utils._compat import decode
...@@ -13,55 +17,122 @@ class Exporter(object): ...@@ -13,55 +17,122 @@ class Exporter(object):
""" """
ACCEPTED_FORMATS = ("requirements.txt",) ACCEPTED_FORMATS = ("requirements.txt",)
ALLOWED_HASH_ALGORITHMS = ("sha256", "sha384", "sha512")
def __init__(self, lock): # type: (Locker) -> None def __init__(self, poetry): # type: (Poetry) -> None
self._lock = lock self._poetry = poetry
def export( def export(
self, fmt, cwd, output, with_hashes=True, dev=False self, fmt, cwd, output, with_hashes=True, dev=False, with_credentials=False
): # type: (str, Path, Union[IO, str], bool, bool) -> None ): # type: (str, Path, Union[IO, str], bool, bool, bool) -> None
if fmt not in self.ACCEPTED_FORMATS: if fmt not in self.ACCEPTED_FORMATS:
raise ValueError("Invalid export format: {}".format(fmt)) raise ValueError("Invalid export format: {}".format(fmt))
getattr(self, "_export_{}".format(fmt.replace(".", "_")))( getattr(self, "_export_{}".format(fmt.replace(".", "_")))(
cwd, output, with_hashes=with_hashes, dev=dev cwd,
output,
with_hashes=with_hashes,
dev=dev,
with_credentials=with_credentials,
) )
def _export_requirements_txt( def _export_requirements_txt(
self, cwd, output, with_hashes=True, dev=False self, cwd, output, with_hashes=True, dev=False, with_credentials=False
): # type: (Path, Union[IO, str], bool, bool) -> None ): # type: (Path, Union[IO, str], bool, bool, bool) -> None
indexes = []
content = "" content = ""
for package in sorted( for package in sorted(
self._lock.locked_repository(dev).packages, key=lambda p: p.name self._poetry.locker.locked_repository(dev).packages, key=lambda p: p.name
): ):
if package.source_type == "git": if package.source_type == "git":
dependency = VCSDependency(
package.name,
package.source_type,
package.source_url,
package.source_reference,
)
dependency.marker = package.marker
line = "-e git+{}@{}#egg={}".format( line = "-e git+{}@{}#egg={}".format(
package.source_url, package.source_reference, package.name package.source_url, package.source_reference, package.name
) )
elif package.source_type in ["directory", "file"]: elif package.source_type in ["directory", "file", "url"]:
line = "" if package.source_type == "file":
dependency = FileDependency(package.name, Path(package.source_url))
elif package.source_type == "directory":
dependency = DirectoryDependency(
package.name, Path(package.source_url)
)
else:
dependency = URLDependency(package.name, package.source_url)
dependency.marker = package.marker
line = "{}".format(package.source_url)
if package.develop: if package.develop:
line += "-e " line = "-e " + line
line += package.source_url
else: else:
line = "{}=={}".format(package.name, package.version.text) dependency = package.to_dependency()
line = "{}=={}".format(package.name, package.version)
if package.source_type == "legacy" and package.source_url: requirement = dependency.to_pep_508()
line += " \\\n" if ";" in requirement:
line += " --index-url {}".format(package.source_url) line += "; {}".format(requirement.split(";")[1].strip())
if package.source_type == "legacy" and package.source_url:
indexes.append(package.source_url)
if package.hashes and with_hashes:
hashes = []
for h in package.hashes:
algorithm = "sha256"
if ":" in h:
algorithm, h = h.split(":")
if package.hashes and with_hashes: if algorithm not in self.ALLOWED_HASH_ALGORITHMS:
continue
hashes.append("{}:{}".format(algorithm, h))
if hashes:
line += " \\\n" line += " \\\n"
for i, h in enumerate(package.hashes): for i, h in enumerate(hashes):
line += " --hash=sha256:{}{}".format( line += " --hash={}{}".format(
h, " \\\n" if i < len(package.hashes) - 1 else "" h, " \\\n" if i < len(package.hashes) - 1 else ""
) )
line += "\n" line += "\n"
content += line content += line
if indexes:
# If we have extra indexes, we add them to the begin
# of the output
indexes_header = ""
for index in indexes:
repository = [
r
for r in self._poetry.pool.repositories
if r.url == index.rstrip("/")
][0]
if (
self._poetry.pool.has_default()
and repository is self._poetry.pool.repositories[0]
):
url = (
repository.authenticated_url
if with_credentials
else repository.url
)
indexes_header = "--index-url {}\n".format(url)
continue
url = (
repository.authenticated_url if with_credentials else repository.url
)
indexes_header += "--extra-index-url {}\n".format(url)
content = indexes_header + "\n" + content
self._output(content, cwd, output) self._output(content, cwd, output)
def _output( def _output(
......
...@@ -3,6 +3,9 @@ import sys ...@@ -3,6 +3,9 @@ import sys
import pytest import pytest
from poetry.packages import Locker as BaseLocker from poetry.packages import Locker as BaseLocker
from poetry.poetry import Poetry
from poetry.repositories.auth import Auth
from poetry.repositories.legacy_repository import LegacyRepository
from poetry.utils._compat import Path from poetry.utils._compat import Path
from poetry.utils.exporter import Exporter from poetry.utils.exporter import Exporter
...@@ -35,8 +38,16 @@ def locker(): ...@@ -35,8 +38,16 @@ def locker():
return Locker() return Locker()
def test_exporter_can_export_requirements_txt_with_standard_packages(tmp_dir, locker): @pytest.fixture
locker.mock_lock_data( def poetry(fixture_dir, locker):
p = Poetry.create(fixture_dir("sample_project"))
p._locker = locker
return p
def test_exporter_can_export_requirements_txt_with_standard_packages(tmp_dir, poetry):
poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
{ {
...@@ -61,7 +72,7 @@ def test_exporter_can_export_requirements_txt_with_standard_packages(tmp_dir, lo ...@@ -61,7 +72,7 @@ def test_exporter_can_export_requirements_txt_with_standard_packages(tmp_dir, lo
}, },
} }
) )
exporter = Exporter(locker) exporter = Exporter(poetry)
exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt")
...@@ -76,10 +87,55 @@ foo==1.2.3 ...@@ -76,10 +87,55 @@ foo==1.2.3
assert expected == content assert expected == content
def test_exporter_can_export_requirements_txt_with_standard_packages_and_markers(
tmp_dir, poetry
):
poetry.locker.mock_lock_data(
{
"package": [
{
"name": "foo",
"version": "1.2.3",
"category": "main",
"optional": False,
"python-versions": "*",
"marker": "python_version < '3.7'",
},
{
"name": "bar",
"version": "4.5.6",
"category": "main",
"optional": False,
"python-versions": "*",
"marker": "extra =='foo'",
},
],
"metadata": {
"python-versions": "*",
"content-hash": "123456789",
"hashes": {"foo": [], "bar": []},
},
}
)
exporter = Exporter(poetry)
exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt")
with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f:
content = f.read()
expected = """\
bar==4.5.6; extra == "foo"
foo==1.2.3; python_version < "3.7"
"""
assert expected == content
def test_exporter_can_export_requirements_txt_with_standard_packages_and_hashes( def test_exporter_can_export_requirements_txt_with_standard_packages_and_hashes(
tmp_dir, locker tmp_dir, poetry
): ):
locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
{ {
...@@ -104,7 +160,7 @@ def test_exporter_can_export_requirements_txt_with_standard_packages_and_hashes( ...@@ -104,7 +160,7 @@ def test_exporter_can_export_requirements_txt_with_standard_packages_and_hashes(
}, },
} }
) )
exporter = Exporter(locker) exporter = Exporter(poetry)
exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt")
...@@ -122,9 +178,9 @@ foo==1.2.3 \\ ...@@ -122,9 +178,9 @@ foo==1.2.3 \\
def test_exporter_can_export_requirements_txt_with_standard_packages_and_hashes_disabled( def test_exporter_can_export_requirements_txt_with_standard_packages_and_hashes_disabled(
tmp_dir, locker tmp_dir, poetry
): ):
locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
{ {
...@@ -149,7 +205,7 @@ def test_exporter_can_export_requirements_txt_with_standard_packages_and_hashes_ ...@@ -149,7 +205,7 @@ def test_exporter_can_export_requirements_txt_with_standard_packages_and_hashes_
}, },
} }
) )
exporter = Exporter(locker) exporter = Exporter(poetry)
exporter.export( exporter.export(
"requirements.txt", Path(tmp_dir), "requirements.txt", with_hashes=False "requirements.txt", Path(tmp_dir), "requirements.txt", with_hashes=False
...@@ -167,9 +223,9 @@ foo==1.2.3 ...@@ -167,9 +223,9 @@ foo==1.2.3
def test_exporter_exports_requirements_txt_without_dev_packages_by_default( def test_exporter_exports_requirements_txt_without_dev_packages_by_default(
tmp_dir, locker tmp_dir, poetry
): ):
locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
{ {
...@@ -194,7 +250,7 @@ def test_exporter_exports_requirements_txt_without_dev_packages_by_default( ...@@ -194,7 +250,7 @@ def test_exporter_exports_requirements_txt_without_dev_packages_by_default(
}, },
} }
) )
exporter = Exporter(locker) exporter = Exporter(poetry)
exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt")
...@@ -210,9 +266,9 @@ foo==1.2.3 \\ ...@@ -210,9 +266,9 @@ foo==1.2.3 \\
def test_exporter_exports_requirements_txt_with_dev_packages_if_opted_in( def test_exporter_exports_requirements_txt_with_dev_packages_if_opted_in(
tmp_dir, locker tmp_dir, poetry
): ):
locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
{ {
...@@ -237,7 +293,7 @@ def test_exporter_exports_requirements_txt_with_dev_packages_if_opted_in( ...@@ -237,7 +293,7 @@ def test_exporter_exports_requirements_txt_with_dev_packages_if_opted_in(
}, },
} }
) )
exporter = Exporter(locker) exporter = Exporter(poetry)
exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt", dev=True) exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt", dev=True)
...@@ -254,8 +310,8 @@ foo==1.2.3 \\ ...@@ -254,8 +310,8 @@ foo==1.2.3 \\
assert expected == content assert expected == content
def test_exporter_can_export_requirements_txt_with_git_packages(tmp_dir, locker): def test_exporter_can_export_requirements_txt_with_git_packages(tmp_dir, poetry):
locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
{ {
...@@ -278,7 +334,7 @@ def test_exporter_can_export_requirements_txt_with_git_packages(tmp_dir, locker) ...@@ -278,7 +334,7 @@ def test_exporter_can_export_requirements_txt_with_git_packages(tmp_dir, locker)
}, },
} }
) )
exporter = Exporter(locker) exporter = Exporter(poetry)
exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt")
...@@ -292,8 +348,10 @@ def test_exporter_can_export_requirements_txt_with_git_packages(tmp_dir, locker) ...@@ -292,8 +348,10 @@ def test_exporter_can_export_requirements_txt_with_git_packages(tmp_dir, locker)
assert expected == content assert expected == content
def test_exporter_can_export_requirements_txt_with_directory_packages(tmp_dir, locker): def test_exporter_can_export_requirements_txt_with_git_packages_and_markers(
locker.mock_lock_data( tmp_dir, poetry
):
poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
{ {
...@@ -302,7 +360,12 @@ def test_exporter_can_export_requirements_txt_with_directory_packages(tmp_dir, l ...@@ -302,7 +360,12 @@ def test_exporter_can_export_requirements_txt_with_directory_packages(tmp_dir, l
"category": "main", "category": "main",
"optional": False, "optional": False,
"python-versions": "*", "python-versions": "*",
"source": {"type": "directory", "url": "../foo", "reference": ""}, "marker": "python_version < '3.7'",
"source": {
"type": "git",
"url": "https://github.com/foo/foo.git",
"reference": "123456",
},
} }
], ],
"metadata": { "metadata": {
...@@ -312,7 +375,7 @@ def test_exporter_can_export_requirements_txt_with_directory_packages(tmp_dir, l ...@@ -312,7 +375,7 @@ def test_exporter_can_export_requirements_txt_with_directory_packages(tmp_dir, l
}, },
} }
) )
exporter = Exporter(locker) exporter = Exporter(poetry)
exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt")
...@@ -320,14 +383,14 @@ def test_exporter_can_export_requirements_txt_with_directory_packages(tmp_dir, l ...@@ -320,14 +383,14 @@ def test_exporter_can_export_requirements_txt_with_directory_packages(tmp_dir, l
content = f.read() content = f.read()
expected = """\ expected = """\
-e ../foo -e git+https://github.com/foo/foo.git@123456#egg=foo; python_version < "3.7"
""" """
assert expected == content assert expected == content
def test_exporter_can_export_requirements_txt_with_file_packages(tmp_dir, locker): def test_exporter_can_export_requirements_txt_with_directory_packages(tmp_dir, poetry):
locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
{ {
...@@ -336,7 +399,11 @@ def test_exporter_can_export_requirements_txt_with_file_packages(tmp_dir, locker ...@@ -336,7 +399,11 @@ def test_exporter_can_export_requirements_txt_with_file_packages(tmp_dir, locker
"category": "main", "category": "main",
"optional": False, "optional": False,
"python-versions": "*", "python-versions": "*",
"source": {"type": "file", "url": "../foo.tar.gz", "reference": ""}, "source": {
"type": "directory",
"url": "tests/fixtures/sample_project",
"reference": "",
},
} }
], ],
"metadata": { "metadata": {
...@@ -346,7 +413,7 @@ def test_exporter_can_export_requirements_txt_with_file_packages(tmp_dir, locker ...@@ -346,7 +413,7 @@ def test_exporter_can_export_requirements_txt_with_file_packages(tmp_dir, locker
}, },
} }
) )
exporter = Exporter(locker) exporter = Exporter(poetry)
exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt")
...@@ -354,14 +421,141 @@ def test_exporter_can_export_requirements_txt_with_file_packages(tmp_dir, locker ...@@ -354,14 +421,141 @@ def test_exporter_can_export_requirements_txt_with_file_packages(tmp_dir, locker
content = f.read() content = f.read()
expected = """\ expected = """\
-e ../foo.tar.gz -e tests/fixtures/sample_project
""" """
assert expected == content assert expected == content
def test_exporter_exports_requirements_txt_with_legacy_packages(tmp_dir, locker): def test_exporter_can_export_requirements_txt_with_directory_packages_and_markers(
locker.mock_lock_data( tmp_dir, poetry
):
poetry.locker.mock_lock_data(
{
"package": [
{
"name": "foo",
"version": "1.2.3",
"category": "main",
"optional": False,
"python-versions": "*",
"marker": "python_version < '3.7'",
"source": {
"type": "directory",
"url": "tests/fixtures/sample_project",
"reference": "",
},
}
],
"metadata": {
"python-versions": "*",
"content-hash": "123456789",
"hashes": {"foo": []},
},
}
)
exporter = Exporter(poetry)
exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt")
with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f:
content = f.read()
expected = """\
-e tests/fixtures/sample_project; python_version < "3.7"
"""
assert expected == content
def test_exporter_can_export_requirements_txt_with_file_packages(tmp_dir, poetry):
poetry.locker.mock_lock_data(
{
"package": [
{
"name": "foo",
"version": "1.2.3",
"category": "main",
"optional": False,
"python-versions": "*",
"source": {
"type": "file",
"url": "tests/fixtures/distributions/demo-0.1.0.tar.gz",
"reference": "",
},
}
],
"metadata": {
"python-versions": "*",
"content-hash": "123456789",
"hashes": {"foo": []},
},
}
)
exporter = Exporter(poetry)
exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt")
with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f:
content = f.read()
expected = """\
-e tests/fixtures/distributions/demo-0.1.0.tar.gz
"""
assert expected == content
def test_exporter_can_export_requirements_txt_with_file_packages_and_markers(
tmp_dir, poetry
):
poetry.locker.mock_lock_data(
{
"package": [
{
"name": "foo",
"version": "1.2.3",
"category": "main",
"optional": False,
"python-versions": "*",
"marker": "python_version < '3.7'",
"source": {
"type": "file",
"url": "tests/fixtures/distributions/demo-0.1.0.tar.gz",
"reference": "",
},
}
],
"metadata": {
"python-versions": "*",
"content-hash": "123456789",
"hashes": {"foo": []},
},
}
)
exporter = Exporter(poetry)
exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt")
with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f:
content = f.read()
expected = """\
-e tests/fixtures/distributions/demo-0.1.0.tar.gz; python_version < "3.7"
"""
assert expected == content
def test_exporter_exports_requirements_txt_with_legacy_packages(tmp_dir, poetry):
poetry.pool.add_repository(
LegacyRepository(
"custom",
"https://example.com/simple",
auth=Auth("https://example.com/simple", "foo", "bar"),
)
)
poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
{ {
...@@ -379,7 +573,7 @@ def test_exporter_exports_requirements_txt_with_legacy_packages(tmp_dir, locker) ...@@ -379,7 +573,7 @@ def test_exporter_exports_requirements_txt_with_legacy_packages(tmp_dir, locker)
"python-versions": "*", "python-versions": "*",
"source": { "source": {
"type": "legacy", "type": "legacy",
"url": "https://example.com/simple/", "url": "https://example.com/simple",
"reference": "", "reference": "",
}, },
}, },
...@@ -391,7 +585,7 @@ def test_exporter_exports_requirements_txt_with_legacy_packages(tmp_dir, locker) ...@@ -391,7 +585,7 @@ def test_exporter_exports_requirements_txt_with_legacy_packages(tmp_dir, locker)
}, },
} }
) )
exporter = Exporter(locker) exporter = Exporter(poetry)
exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt", dev=True) exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt", dev=True)
...@@ -399,8 +593,74 @@ def test_exporter_exports_requirements_txt_with_legacy_packages(tmp_dir, locker) ...@@ -399,8 +593,74 @@ def test_exporter_exports_requirements_txt_with_legacy_packages(tmp_dir, locker)
content = f.read() content = f.read()
expected = """\ expected = """\
--extra-index-url https://example.com/simple
bar==4.5.6 \\
--hash=sha256:67890
foo==1.2.3 \\
--hash=sha256:12345
"""
assert expected == content
def test_exporter_exports_requirements_txt_with_legacy_packages_and_credentials(
tmp_dir, poetry, config
):
poetry.pool.add_repository(
LegacyRepository(
"custom",
"https://example.com/simple",
auth=Auth("https://example.com/simple", "foo", "bar"),
)
)
poetry.locker.mock_lock_data(
{
"package": [
{
"name": "foo",
"version": "1.2.3",
"category": "main",
"optional": False,
"python-versions": "*",
},
{
"name": "bar",
"version": "4.5.6",
"category": "dev",
"optional": False,
"python-versions": "*",
"source": {
"type": "legacy",
"url": "https://example.com/simple",
"reference": "",
},
},
],
"metadata": {
"python-versions": "*",
"content-hash": "123456789",
"hashes": {"foo": ["12345"], "bar": ["67890"]},
},
}
)
exporter = Exporter(poetry)
exporter.export(
"requirements.txt",
Path(tmp_dir),
"requirements.txt",
dev=True,
with_credentials=True,
)
with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f:
content = f.read()
expected = """\
--extra-index-url https://foo:bar@example.com/simple
bar==4.5.6 \\ bar==4.5.6 \\
--index-url https://example.com/simple/ \\
--hash=sha256:67890 --hash=sha256:67890
foo==1.2.3 \\ foo==1.2.3 \\
--hash=sha256:12345 --hash=sha256:12345
...@@ -409,8 +669,8 @@ foo==1.2.3 \\ ...@@ -409,8 +669,8 @@ foo==1.2.3 \\
assert expected == content assert expected == content
def test_exporter_exports_requirements_txt_to_standard_output(tmp_dir, locker, capsys): def test_exporter_exports_requirements_txt_to_standard_output(tmp_dir, poetry, capsys):
locker.mock_lock_data( poetry.locker.mock_lock_data(
{ {
"package": [ "package": [
{ {
...@@ -435,7 +695,7 @@ def test_exporter_exports_requirements_txt_to_standard_output(tmp_dir, locker, c ...@@ -435,7 +695,7 @@ def test_exporter_exports_requirements_txt_to_standard_output(tmp_dir, locker, c
}, },
} }
) )
exporter = Exporter(locker) exporter = Exporter(poetry)
exporter.export("requirements.txt", Path(tmp_dir), sys.stdout) exporter.export("requirements.txt", Path(tmp_dir), sys.stdout)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment