Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
python-poetry
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open
python-poetry
Commits
bd64610e
Commit
bd64610e
authored
Apr 05, 2022
by
Arun Babu Neelicattu
Committed by
Randy Döring
Apr 16, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
export: remove in-tree export logic
parent
d52780c5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
0 additions
and
2591 deletions
+0
-2591
src/poetry/console/application.py
+0
-1
src/poetry/console/commands/export.py
+0
-80
src/poetry/utils/exporter.py
+0
-182
tests/console/commands/test_export.py
+0
-160
tests/utils/test_exporter.py
+0
-2168
No files found.
src/poetry/console/application.py
View file @
bd64610e
...
@@ -53,7 +53,6 @@ COMMANDS = [
...
@@ -53,7 +53,6 @@ COMMANDS = [
"build"
,
"build"
,
"check"
,
"check"
,
"config"
,
"config"
,
"export"
,
"init"
,
"init"
,
"install"
,
"install"
,
"lock"
,
"lock"
,
...
...
src/poetry/console/commands/export.py
deleted
100644 → 0
View file @
d52780c5
from
__future__
import
annotations
from
cleo.helpers
import
option
from
poetry.console.commands.command
import
Command
from
poetry.utils.exporter
import
Exporter
class
ExportCommand
(
Command
):
name
=
"export"
description
=
"Exports the lock file to alternative formats."
options
=
[
option
(
"format"
,
"f"
,
"Format to export to. Currently, only requirements.txt is supported."
,
flag
=
False
,
default
=
Exporter
.
FORMAT_REQUIREMENTS_TXT
,
),
option
(
"output"
,
"o"
,
"The name of the output file."
,
flag
=
False
),
option
(
"without-hashes"
,
None
,
"Exclude hashes from the exported file."
),
option
(
"without-urls"
,
None
,
"Exclude source repository urls from the exported file."
,
),
option
(
"dev"
,
None
,
"Include development dependencies."
),
option
(
"extras"
,
"E"
,
"Extra sets of dependencies to include."
,
flag
=
False
,
multiple
=
True
,
),
option
(
"with-credentials"
,
None
,
"Include credentials for extra indices."
),
]
def
handle
(
self
)
->
None
:
fmt
=
self
.
option
(
"format"
)
if
fmt
not
in
Exporter
.
ACCEPTED_FORMATS
:
raise
ValueError
(
f
"Invalid export format: {fmt}"
)
output
=
self
.
option
(
"output"
)
locker
=
self
.
poetry
.
locker
if
not
locker
.
is_locked
():
self
.
line_error
(
"<comment>The lock file does not exist. Locking.</comment>"
)
options
=
[]
if
self
.
io
.
is_debug
():
options
.
append
(
"-vvv"
)
elif
self
.
io
.
is_very_verbose
():
options
.
append
(
"-vv"
)
elif
self
.
io
.
is_verbose
():
options
.
append
(
"-v"
)
self
.
call
(
"lock"
,
" "
.
join
(
options
))
if
not
locker
.
is_fresh
():
self
.
line_error
(
"<warning>"
"Warning: poetry.lock is not consistent with pyproject.toml. "
"You may be getting improper dependencies. "
"Run `poetry lock [--no-update]` to fix it."
"</warning>"
)
exporter
=
Exporter
(
self
.
poetry
)
exporter
.
export
(
fmt
,
self
.
poetry
.
file
.
parent
,
output
or
self
.
io
,
with_hashes
=
not
self
.
option
(
"without-hashes"
),
dev
=
self
.
option
(
"dev"
),
extras
=
self
.
option
(
"extras"
),
with_credentials
=
self
.
option
(
"with-credentials"
),
with_urls
=
not
self
.
option
(
"without-urls"
),
)
src/poetry/utils/exporter.py
deleted
100644 → 0
View file @
d52780c5
from
__future__
import
annotations
import
urllib.parse
from
typing
import
TYPE_CHECKING
from
typing
import
Sequence
from
poetry.core.packages.utils.utils
import
path_to_url
from
poetry.utils._compat
import
decode
if
TYPE_CHECKING
:
from
pathlib
import
Path
from
cleo.io.io
import
IO
from
poetry.poetry
import
Poetry
class
Exporter
:
"""
Exporter class to export a lock file to alternative formats.
"""
FORMAT_REQUIREMENTS_TXT
=
"requirements.txt"
#: The names of the supported export formats.
ACCEPTED_FORMATS
=
(
FORMAT_REQUIREMENTS_TXT
,)
ALLOWED_HASH_ALGORITHMS
=
(
"sha256"
,
"sha384"
,
"sha512"
)
def
__init__
(
self
,
poetry
:
Poetry
)
->
None
:
self
.
_poetry
=
poetry
def
export
(
self
,
fmt
:
str
,
cwd
:
Path
,
output
:
IO
|
str
,
with_hashes
:
bool
=
True
,
dev
:
bool
=
False
,
extras
:
bool
|
Sequence
[
str
]
|
None
=
None
,
with_credentials
:
bool
=
False
,
with_urls
:
bool
=
True
,
)
->
None
:
if
fmt
not
in
self
.
ACCEPTED_FORMATS
:
raise
ValueError
(
f
"Invalid export format: {fmt}"
)
getattr
(
self
,
"_export_"
+
fmt
.
replace
(
"."
,
"_"
))(
cwd
,
output
,
with_hashes
=
with_hashes
,
dev
=
dev
,
extras
=
extras
,
with_credentials
=
with_credentials
,
with_urls
=
with_urls
,
)
def
_export_requirements_txt
(
self
,
cwd
:
Path
,
output
:
IO
|
str
,
with_hashes
:
bool
=
True
,
dev
:
bool
=
False
,
extras
:
bool
|
Sequence
[
str
]
|
None
=
None
,
with_credentials
:
bool
=
False
,
with_urls
:
bool
=
True
,
)
->
None
:
indexes
=
set
()
content
=
""
dependency_lines
=
set
()
# Get project dependencies.
root_package
=
(
self
.
_poetry
.
package
.
clone
()
if
dev
else
self
.
_poetry
.
package
.
with_dependency_groups
([
"default"
],
only
=
True
)
)
for
dependency_package
in
self
.
_poetry
.
locker
.
get_project_dependency_packages
(
project_requires
=
root_package
.
all_requires
,
project_python_marker
=
root_package
.
python_marker
,
dev
=
dev
,
extras
=
extras
,
):
line
=
""
dependency
=
dependency_package
.
dependency
package
=
dependency_package
.
package
if
package
.
develop
:
line
+=
"-e "
requirement
=
dependency
.
to_pep_508
(
with_extras
=
False
)
is_direct_local_reference
=
(
dependency
.
is_file
()
or
dependency
.
is_directory
()
)
is_direct_remote_reference
=
dependency
.
is_vcs
()
or
dependency
.
is_url
()
if
is_direct_remote_reference
:
line
=
requirement
elif
is_direct_local_reference
:
dependency_uri
=
path_to_url
(
dependency
.
source_url
)
line
=
f
"{dependency.name} @ {dependency_uri}"
else
:
line
=
f
"{package.name}=={package.version}"
if
not
is_direct_remote_reference
and
";"
in
requirement
:
markers
=
requirement
.
split
(
";"
,
1
)[
1
]
.
strip
()
if
markers
:
line
+=
f
" ; {markers}"
if
(
not
is_direct_remote_reference
and
not
is_direct_local_reference
and
package
.
source_url
):
indexes
.
add
(
package
.
source_url
)
if
package
.
files
and
with_hashes
:
hashes
=
[]
for
f
in
package
.
files
:
h
=
f
[
"hash"
]
algorithm
=
"sha256"
if
":"
in
h
:
algorithm
,
h
=
h
.
split
(
":"
)
if
algorithm
not
in
self
.
ALLOWED_HASH_ALGORITHMS
:
continue
hashes
.
append
(
f
"{algorithm}:{h}"
)
if
hashes
:
sep
=
"
\\\n
"
line
+=
sep
+
sep
.
join
(
f
" --hash={h}"
for
h
in
hashes
)
dependency_lines
.
add
(
line
)
content
+=
"
\n
"
.
join
(
sorted
(
dependency_lines
))
content
+=
"
\n
"
if
indexes
and
with_urls
:
# If we have extra indexes, we add them to the beginning of the output
indexes_header
=
""
for
index
in
sorted
(
indexes
):
repositories
=
[
r
for
r
in
self
.
_poetry
.
pool
.
repositories
if
r
.
url
==
index
.
rstrip
(
"/"
)
]
if
not
repositories
:
continue
repository
=
repositories
[
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
=
f
"--index-url {url}
\n
"
continue
url
=
(
repository
.
authenticated_url
if
with_credentials
else
repository
.
url
)
parsed_url
=
urllib
.
parse
.
urlsplit
(
url
)
if
parsed_url
.
scheme
==
"http"
:
indexes_header
+=
f
"--trusted-host {parsed_url.netloc}
\n
"
indexes_header
+=
f
"--extra-index-url {url}
\n
"
content
=
indexes_header
+
"
\n
"
+
content
self
.
_output
(
content
,
cwd
,
output
)
def
_output
(
self
,
content
:
str
,
cwd
:
Path
,
output
:
IO
|
str
)
->
None
:
decoded
=
decode
(
content
)
try
:
output
.
write
(
decoded
)
except
AttributeError
:
filepath
=
cwd
/
output
with
filepath
.
open
(
"w"
,
encoding
=
"utf-8"
)
as
f
:
f
.
write
(
decoded
)
tests/console/commands/test_export.py
deleted
100644 → 0
View file @
d52780c5
from
__future__
import
annotations
from
typing
import
TYPE_CHECKING
from
unittest.mock
import
Mock
import
pytest
from
poetry_plugin_export.exporter
import
Exporter
from
tests.helpers
import
get_package
if
TYPE_CHECKING
:
from
_pytest.monkeypatch
import
MonkeyPatch
from
cleo.testers.command_tester
import
CommandTester
from
poetry.poetry
import
Poetry
from
tests.helpers
import
TestRepository
from
tests.types
import
CommandTesterFactory
from
tests.types
import
ProjectFactory
PYPROJECT_CONTENT
=
"""
\
[tool.poetry]
name = "simple-project"
version = "1.2.3"
description = "Some description."
authors = [
"Sébastien Eustace <sebastien@eustace.io>"
]
license = "MIT"
readme = "README.rst"
homepage = "https://python-poetry.org"
repository = "https://github.com/python-poetry/poetry"
documentation = "https://python-poetry.org/docs"
keywords = ["packaging", "dependency", "poetry"]
classifiers = [
"Topic :: Software Development :: Build Tools",
"Topic :: Software Development :: Libraries :: Python Modules"
]
# Requirements
[tool.poetry.dependencies]
python = "~2.7 || ^3.4"
foo = "^1.0"
bar = { version = "^1.1", optional = true }
[tool.poetry.extras]
feature_bar = ["bar"]
"""
@pytest.fixture
(
autouse
=
True
)
def
setup
(
repo
:
TestRepository
)
->
None
:
repo
.
add_package
(
get_package
(
"foo"
,
"1.0.0"
))
repo
.
add_package
(
get_package
(
"bar"
,
"1.1.0"
))
@pytest.fixture
def
poetry
(
project_factory
:
ProjectFactory
)
->
Poetry
:
return
project_factory
(
name
=
"export"
,
pyproject_content
=
PYPROJECT_CONTENT
)
@pytest.fixture
def
tester
(
command_tester_factory
:
CommandTesterFactory
,
poetry
:
Poetry
)
->
CommandTester
:
return
command_tester_factory
(
"export"
,
poetry
=
poetry
)
def
_export_requirements
(
tester
:
CommandTester
,
poetry
:
Poetry
)
->
None
:
tester
.
execute
(
"--format requirements.txt --output requirements.txt"
)
requirements
=
poetry
.
file
.
parent
/
"requirements.txt"
assert
requirements
.
exists
()
with
requirements
.
open
(
encoding
=
"utf-8"
)
as
f
:
content
=
f
.
read
()
assert
poetry
.
locker
.
lock
.
exists
()
expected
=
"""
\
foo==1.0.0 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.4" and python_version < "4.0"
"""
assert
content
==
expected
def
test_export_exports_requirements_txt_file_locks_if_no_lock_file
(
tester
:
CommandTester
,
poetry
:
Poetry
):
assert
not
poetry
.
locker
.
lock
.
exists
()
_export_requirements
(
tester
,
poetry
)
assert
"The lock file does not exist. Locking."
in
tester
.
io
.
fetch_error
()
def
test_export_exports_requirements_txt_uses_lock_file
(
tester
:
CommandTester
,
poetry
:
Poetry
,
do_lock
:
None
):
_export_requirements
(
tester
,
poetry
)
assert
"The lock file does not exist. Locking."
not
in
tester
.
io
.
fetch_error
()
def
test_export_fails_on_invalid_format
(
tester
:
CommandTester
,
do_lock
:
None
):
with
pytest
.
raises
(
ValueError
):
tester
.
execute
(
"--format invalid"
)
def
test_export_prints_to_stdout_by_default
(
tester
:
CommandTester
,
do_lock
:
None
):
tester
.
execute
(
"--format requirements.txt"
)
expected
=
"""
\
foo==1.0.0 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.4" and python_version < "4.0"
"""
assert
tester
.
io
.
fetch_output
()
==
expected
def
test_export_uses_requirements_txt_format_by_default
(
tester
:
CommandTester
,
do_lock
:
None
):
tester
.
execute
()
expected
=
"""
\
foo==1.0.0 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.4" and python_version < "4.0"
"""
assert
tester
.
io
.
fetch_output
()
==
expected
def
test_export_includes_extras_by_flag
(
tester
:
CommandTester
,
do_lock
:
None
):
tester
.
execute
(
"--format requirements.txt --extras feature_bar"
)
expected
=
"""
\
bar==1.1.0 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.4" and python_version < "4.0"
foo==1.0.0 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.4" and python_version < "4.0"
"""
assert
tester
.
io
.
fetch_output
()
==
expected
def
test_export_with_urls
(
monkeypatch
:
MonkeyPatch
,
tester
:
CommandTester
,
poetry
:
Poetry
):
"""
We are just validating that the option gets passed. The option itself is tested in
the Exporter test.
"""
mock_export
=
Mock
()
monkeypatch
.
setattr
(
Exporter
,
"with_urls"
,
mock_export
)
tester
.
execute
(
"--without-urls"
)
mock_export
.
assert_called_once_with
(
False
)
tests/utils/test_exporter.py
deleted
100644 → 0
View file @
d52780c5
from
__future__
import
annotations
import
sys
from
pathlib
import
Path
from
typing
import
TYPE_CHECKING
from
typing
import
Any
from
typing
import
Iterator
import
pytest
from
poetry.core.packages.dependency
import
Dependency
from
poetry.core.toml.file
import
TOMLFile
from
poetry.factory
import
Factory
from
poetry.packages
import
Locker
as
BaseLocker
from
poetry.repositories.legacy_repository
import
LegacyRepository
from
poetry.utils.exporter
import
Exporter
if
TYPE_CHECKING
:
from
_pytest.capture
import
CaptureFixture
from
pytest_mock
import
MockerFixture
from
poetry.poetry
import
Poetry
from
tests.conftest
import
Config
from
tests.types
import
FixtureDirGetter
class
Locker
(
BaseLocker
):
def
__init__
(
self
)
->
None
:
self
.
_lock
=
TOMLFile
(
Path
.
cwd
()
.
joinpath
(
"poetry.lock"
))
self
.
_locked
=
True
self
.
_content_hash
=
self
.
_get_content_hash
()
def
locked
(
self
,
is_locked
:
bool
=
True
)
->
Locker
:
self
.
_locked
=
is_locked
return
self
def
mock_lock_data
(
self
,
data
:
dict
[
str
,
Any
]):
self
.
_lock_data
=
data
def
is_locked
(
self
)
->
bool
:
return
self
.
_locked
def
is_fresh
(
self
)
->
bool
:
return
True
def
_get_content_hash
(
self
)
->
str
:
return
"123456789"
@pytest.fixture
def
working_directory
()
->
Path
:
return
Path
(
__file__
)
.
parent
.
parent
.
parent
@pytest.fixture
(
autouse
=
True
)
def
mock_path_cwd
(
mocker
:
MockerFixture
,
working_directory
:
Path
)
->
Iterator
[
MockerFixture
]:
yield
mocker
.
patch
(
"pathlib.Path.cwd"
,
return_value
=
working_directory
)
@pytest.fixture
()
def
locker
()
->
Locker
:
return
Locker
()
@pytest.fixture
def
poetry
(
fixture_dir
:
FixtureDirGetter
,
locker
:
Locker
)
->
Poetry
:
p
=
Factory
()
.
create_poetry
(
fixture_dir
(
"sample_project"
))
p
.
_locker
=
locker
return
p
def
set_package_requires
(
poetry
:
Poetry
,
skip
:
set
[
str
]
|
None
=
None
)
->
None
:
skip
=
skip
or
set
()
packages
=
poetry
.
locker
.
locked_repository
(
with_dev_reqs
=
True
)
.
packages
package
=
poetry
.
package
.
with_dependency_groups
([],
only
=
True
)
for
pkg
in
packages
:
if
pkg
.
name
not
in
skip
:
package
.
add_dependency
(
pkg
.
to_dependency
())
poetry
.
_package
=
package
def
test_exporter_can_export_requirements_txt_with_standard_packages
(
tmp_dir
:
str
,
poetry
:
Poetry
):
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"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
},
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"foo"
:
[],
"bar"
:
[]},
},
}
)
set_package_requires
(
poetry
)
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 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
foo==1.2.3 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
"""
assert
content
==
expected
def
test_exporter_can_export_requirements_txt_with_standard_packages_and_markers
(
tmp_dir
:
str
,
poetry
:
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'"
,
},
{
"name"
:
"baz"
,
"version"
:
"7.8.9"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"marker"
:
"sys_platform == 'win32'"
,
},
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"foo"
:
[],
"bar"
:
[],
"baz"
:
[]},
},
}
)
set_package_requires
(
poetry
)
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 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
baz==7.8.9 ;
\
python_version >= "2.7" and python_version < "2.8" and sys_platform == "win32" or
\
python_version >= "3.6" and python_version < "4.0" and sys_platform == "win32"
foo==1.2.3 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "3.7"
"""
assert
content
==
expected
def
test_exporter_can_export_requirements_txt_poetry
(
tmp_dir
:
str
,
poetry
:
Poetry
):
"""Regression test for #3254"""
poetry
.
locker
.
mock_lock_data
(
{
"package"
:
[
{
"name"
:
"poetry"
,
"version"
:
"1.1.4"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"dependencies"
:
{
"keyring"
:
"*"
},
},
{
"name"
:
"junit-xml"
,
"version"
:
"1.9"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"dependencies"
:
{
"six"
:
"*"
},
},
{
"name"
:
"keyring"
,
"version"
:
"21.8.0"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"dependencies"
:
{
"SecretStorage"
:
{
"version"
:
"*"
,
"markers"
:
"sys_platform == 'linux'"
,
}
},
},
{
"name"
:
"secretstorage"
,
"version"
:
"3.3.0"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"dependencies"
:
{
"cryptography"
:
"*"
},
},
{
"name"
:
"cryptography"
,
"version"
:
"3.2"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"dependencies"
:
{
"six"
:
"*"
},
},
{
"name"
:
"six"
,
"version"
:
"1.15.0"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
},
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"poetry"
:
[],
"keyring"
:
[],
"secretstorage"
:
[],
"cryptography"
:
[],
"six"
:
[],
"junit-xml"
:
[],
},
},
}
)
set_package_requires
(
poetry
,
skip
=
{
"keyring"
,
"secretstorage"
,
"cryptography"
,
"six"
}
)
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
()
# The dependency graph:
# junit-xml 1.9 Creates JUnit XML test result documents that can be read by tools
# └── six * such as Jenkins
# poetry 1.1.4 Python dependency management and packaging made easy.
# ├── keyring >=21.2.0,<22.0.0
# │ ├── importlib-metadata >=1
# │ │ └── zipp >=0.5
# │ ├── jeepney >=0.4.2
# │ ├── pywin32-ctypes <0.1.0 || >0.1.0,<0.1.1 || >0.1.1
# │ └── secretstorage >=3.2 -- On linux only
# │ ├── cryptography >=2.0
# │ │ └── six >=1.4.1
# │ └── jeepney >=0.6 (circular dependency aborted here)
python27
=
'python_version >= "2.7" and python_version < "2.8"'
python36
=
'python_version >= "3.6" and python_version < "4.0"'
linux
=
'sys_platform=="linux"'
expected
=
{
"poetry"
:
Dependency
.
create_from_pep_508
(
f
"poetry==1.1.4; {python27} or {python36}"
),
"junit-xml"
:
Dependency
.
create_from_pep_508
(
f
"junit-xml==1.9 ; {python27} or {python36}"
),
"keyring"
:
Dependency
.
create_from_pep_508
(
f
"keyring==21.8.0 ; {python27} or {python36}"
),
"secretstorage"
:
Dependency
.
create_from_pep_508
(
f
"secretstorage==3.3.0 ; {python27} and {linux} or {python36} and {linux}"
),
"cryptography"
:
Dependency
.
create_from_pep_508
(
f
"cryptography==3.2 ; {python27} and {linux} or {python36} and {linux}"
),
"six"
:
Dependency
.
create_from_pep_508
(
f
"six==1.15.0 ; {python27} or {python36} or {python27} and {linux} or"
f
" {python36} and {linux}"
),
}
for
line
in
content
.
strip
()
.
split
(
"
\n
"
):
dependency
=
Dependency
.
create_from_pep_508
(
line
)
assert
dependency
.
name
in
expected
expected_dependency
=
expected
.
pop
(
dependency
.
name
)
assert
dependency
==
expected_dependency
assert
dependency
.
marker
==
expected_dependency
.
marker
def
test_exporter_can_export_requirements_txt_pyinstaller
(
tmp_dir
:
str
,
poetry
:
Poetry
):
"""Regression test for #3254"""
poetry
.
locker
.
mock_lock_data
(
{
"package"
:
[
{
"name"
:
"pyinstaller"
,
"version"
:
"4.0"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"dependencies"
:
{
"altgraph"
:
"*"
,
"macholib"
:
{
"version"
:
"*"
,
"markers"
:
"sys_platform == 'darwin'"
,
},
},
},
{
"name"
:
"altgraph"
,
"version"
:
"0.17"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
},
{
"name"
:
"macholib"
,
"version"
:
"1.8"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"dependencies"
:
{
"altgraph"
:
">=0.15"
},
},
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"pyinstaller"
:
[],
"altgraph"
:
[],
"macholib"
:
[]},
},
}
)
set_package_requires
(
poetry
,
skip
=
{
"altgraph"
,
"macholib"
})
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
()
# Rationale for the results:
# * PyInstaller has an explicit dependency on altgraph, so it must always be
# installed.
# * PyInstaller requires macholib on Darwin, which in turn requires altgraph.
# The dependency graph:
# pyinstaller 4.0 PyInstaller bundles a Python application and all its
# ├── altgraph * dependencies into a single package.
# ├── macholib >=1.8 -- only on Darwin
# │ └── altgraph >=0.15
python27
=
'python_version >= "2.7" and python_version < "2.8"'
python36
=
'python_version >= "3.6" and python_version < "4.0"'
darwin
=
'sys_platform=="darwin"'
expected
=
{
"pyinstaller"
:
Dependency
.
create_from_pep_508
(
f
"pyinstaller==4.0 ; {python27} or {python36}"
),
"altgraph"
:
Dependency
.
create_from_pep_508
(
f
"altgraph==0.17 ; {python27} or {python36} or {python27} and {darwin} or"
f
" {python36} and {darwin}"
),
"macholib"
:
Dependency
.
create_from_pep_508
(
f
"macholib==1.8 ; {python27} and {darwin} or {python36} and {darwin}"
),
}
for
line
in
content
.
strip
()
.
split
(
"
\n
"
):
dependency
=
Dependency
.
create_from_pep_508
(
line
)
assert
dependency
.
name
in
expected
expected_dependency
=
expected
.
pop
(
dependency
.
name
)
assert
dependency
==
expected_dependency
assert
dependency
.
marker
==
expected_dependency
.
marker
def
test_exporter_can_export_requirements_txt_with_nested_packages_and_markers
(
tmp_dir
:
str
,
poetry
:
Poetry
):
poetry
.
locker
.
mock_lock_data
(
{
"package"
:
[
{
"name"
:
"a"
,
"version"
:
"1.2.3"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"marker"
:
"python_version < '3.7'"
,
"dependencies"
:
{
"b"
:
">=0.0.0"
,
"c"
:
">=0.0.0"
},
},
{
"name"
:
"b"
,
"version"
:
"4.5.6"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"marker"
:
"platform_system == 'Windows'"
,
"dependencies"
:
{
"d"
:
">=0.0.0"
},
},
{
"name"
:
"c"
,
"version"
:
"7.8.9"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"marker"
:
"sys_platform == 'win32'"
,
"dependencies"
:
{
"d"
:
">=0.0.0"
},
},
{
"name"
:
"d"
,
"version"
:
"0.0.1"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
},
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"a"
:
[],
"b"
:
[],
"c"
:
[],
"d"
:
[]},
},
}
)
set_package_requires
(
poetry
,
skip
=
{
"b"
,
"c"
,
"d"
})
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
()
python27
=
'python_version >= "2.7" and python_version < "2.8"'
python36
=
'python_version >= "3.6" and python_version < "3.7"'
windows
=
'platform_system == "Windows"'
win32
=
'sys_platform == "win32"'
expected
=
{
"a"
:
Dependency
.
create_from_pep_508
(
f
"a==1.2.3 ; {python27} or {python36}"
),
"b"
:
Dependency
.
create_from_pep_508
(
f
"b==4.5.6 ; {python27} and {windows} or {python36} and {windows}"
),
"c"
:
Dependency
.
create_from_pep_508
(
f
"c==7.8.9 ; {python27} and {win32} or {python36} and {win32}"
),
"d"
:
Dependency
.
create_from_pep_508
(
f
"d==0.0.1 ; {python27} and {windows} or {python36} and {windows} or"
f
" {python27} and {win32} or {python36} and {win32}"
),
}
for
line
in
content
.
strip
()
.
split
(
"
\n
"
):
dependency
=
Dependency
.
create_from_pep_508
(
line
)
assert
dependency
.
name
in
expected
expected_dependency
=
expected
.
pop
(
dependency
.
name
)
assert
dependency
==
expected_dependency
assert
dependency
.
marker
==
expected_dependency
.
marker
assert
expected
==
{}
@pytest.mark.parametrize
(
[
"dev"
,
"lines"
],
[
(
False
,
[
'a==1.2.3 ; python_version >= "2.7" and python_version < "2.8" or'
' python_version >= "3.6" and python_version < "3.8"'
],
),
(
True
,
[
'a==1.2.3 ; python_version >= "2.7" and python_version < "2.8" or'
' python_version >= "3.6" and python_version < "3.8" or python_version'
' >= "3.6" and python_version < "4.0"'
,
'b==4.5.6 ; python_version >= "2.7" and python_version < "2.8" or'
' python_version >= "3.6" and python_version < "4.0"'
,
],
),
],
)
def
test_exporter_can_export_requirements_txt_with_nested_packages_and_markers_any
(
tmp_dir
:
str
,
poetry
:
Poetry
,
dev
:
bool
,
lines
:
list
[
str
]
):
poetry
.
locker
.
mock_lock_data
(
{
"package"
:
[
{
"name"
:
"a"
,
"version"
:
"1.2.3"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
},
{
"name"
:
"b"
,
"version"
:
"4.5.6"
,
"category"
:
"dev"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"dependencies"
:
{
"a"
:
">=1.2.3"
},
},
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"a"
:
[],
"b"
:
[]},
},
}
)
root
=
poetry
.
package
.
with_dependency_groups
([],
only
=
True
)
root
.
add_dependency
(
Factory
.
create_dependency
(
name
=
"a"
,
constraint
=
{
"version"
:
"^1.2.3"
,
"python"
:
"<3.8"
}
)
)
root
.
add_dependency
(
Factory
.
create_dependency
(
name
=
"b"
,
constraint
=
{
"version"
:
"^4.5.6"
},
groups
=
[
"dev"
]
)
)
poetry
.
_package
=
root
exporter
=
Exporter
(
poetry
)
exporter
.
export
(
"requirements.txt"
,
Path
(
tmp_dir
),
"requirements.txt"
,
dev
=
dev
)
with
(
Path
(
tmp_dir
)
/
"requirements.txt"
)
.
open
(
encoding
=
"utf-8"
)
as
f
:
content
=
f
.
read
()
assert
content
.
strip
()
==
"
\n
"
.
join
(
lines
)
def
test_exporter_can_export_requirements_txt_with_standard_packages_and_hashes
(
tmp_dir
:
str
,
poetry
:
Poetry
):
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"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
},
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"foo"
:
[
"12345"
],
"bar"
:
[
"67890"
]},
},
}
)
set_package_requires
(
poetry
)
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 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
\\
--hash=sha256:67890
foo==1.2.3 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
\\
--hash=sha256:12345
"""
assert
content
==
expected
def
test_exporter_can_export_requirements_txt_with_standard_packages_and_hashes_disabled
(
# noqa: E501
tmp_dir
:
str
,
poetry
:
Poetry
):
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"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
},
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"foo"
:
[
"12345"
],
"bar"
:
[
"67890"
]},
},
}
)
set_package_requires
(
poetry
)
exporter
=
Exporter
(
poetry
)
exporter
.
export
(
"requirements.txt"
,
Path
(
tmp_dir
),
"requirements.txt"
,
with_hashes
=
False
)
with
(
Path
(
tmp_dir
)
/
"requirements.txt"
)
.
open
(
encoding
=
"utf-8"
)
as
f
:
content
=
f
.
read
()
expected
=
"""
\
bar==4.5.6 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
foo==1.2.3 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
"""
assert
content
==
expected
def
test_exporter_exports_requirements_txt_without_dev_packages_by_default
(
tmp_dir
:
str
,
poetry
:
Poetry
):
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"
:
"*"
,
},
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"foo"
:
[
"12345"
],
"bar"
:
[
"67890"
]},
},
}
)
set_package_requires
(
poetry
)
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
=
"""
\
foo==1.2.3 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
\\
--hash=sha256:12345
"""
assert
content
==
expected
def
test_exporter_exports_requirements_txt_with_dev_packages_if_opted_in
(
tmp_dir
:
str
,
poetry
:
Poetry
):
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"
:
"*"
,
},
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"foo"
:
[
"12345"
],
"bar"
:
[
"67890"
]},
},
}
)
set_package_requires
(
poetry
)
exporter
=
Exporter
(
poetry
)
exporter
.
export
(
"requirements.txt"
,
Path
(
tmp_dir
),
"requirements.txt"
,
dev
=
True
)
with
(
Path
(
tmp_dir
)
/
"requirements.txt"
)
.
open
(
encoding
=
"utf-8"
)
as
f
:
content
=
f
.
read
()
expected
=
"""
\
bar==4.5.6 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
\\
--hash=sha256:67890
foo==1.2.3 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
\\
--hash=sha256:12345
"""
assert
content
==
expected
def
test_exporter_exports_requirements_txt_without_optional_packages
(
tmp_dir
:
str
,
poetry
:
Poetry
):
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"
:
True
,
"python-versions"
:
"*"
,
},
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"foo"
:
[
"12345"
],
"bar"
:
[
"67890"
]},
},
}
)
set_package_requires
(
poetry
)
exporter
=
Exporter
(
poetry
)
exporter
.
export
(
"requirements.txt"
,
Path
(
tmp_dir
),
"requirements.txt"
,
dev
=
True
)
with
(
Path
(
tmp_dir
)
/
"requirements.txt"
)
.
open
(
encoding
=
"utf-8"
)
as
f
:
content
=
f
.
read
()
expected
=
"""
\
foo==1.2.3 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
\\
--hash=sha256:12345
"""
assert
content
==
expected
@pytest.mark.parametrize
(
[
"extras"
,
"lines"
],
[
(
None
,
[
'foo==1.2.3 ; python_version >= "2.7" and python_version < "2.8" or'
' python_version >= "3.6" and python_version < "4.0"'
],
),
(
False
,
[
'foo==1.2.3 ; python_version >= "2.7" and python_version < "2.8" or'
' python_version >= "3.6" and python_version < "4.0"'
],
),
(
True
,
[
'bar==4.5.6 ; python_version >= "2.7" and python_version < "2.8" or'
' python_version >= "3.6" and python_version < "4.0"'
,
'foo==1.2.3 ; python_version >= "2.7" and python_version < "2.8" or'
' python_version >= "3.6" and python_version < "4.0"'
,
'spam==0.1.0 ; python_version >= "2.7" and python_version < "2.8" or'
' python_version >= "3.6" and python_version < "4.0"'
,
],
),
(
[
"feature_bar"
],
[
'bar==4.5.6 ; python_version >= "2.7" and python_version < "2.8" or'
' python_version >= "3.6" and python_version < "4.0"'
,
'foo==1.2.3 ; python_version >= "2.7" and python_version < "2.8" or'
' python_version >= "3.6" and python_version < "4.0"'
,
'spam==0.1.0 ; python_version >= "2.7" and python_version < "2.8" or'
' python_version >= "3.6" and python_version < "4.0"'
,
],
),
],
)
def
test_exporter_exports_requirements_txt_with_optional_packages
(
tmp_dir
:
str
,
poetry
:
Poetry
,
extras
:
bool
|
list
[
str
]
|
None
,
lines
:
list
[
str
],
):
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"
:
"main"
,
"optional"
:
True
,
"python-versions"
:
"*"
,
"dependencies"
:
{
"spam"
:
">=0.1"
},
},
{
"name"
:
"spam"
,
"version"
:
"0.1.0"
,
"category"
:
"main"
,
"optional"
:
True
,
"python-versions"
:
"*"
,
},
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"foo"
:
[
"12345"
],
"bar"
:
[
"67890"
],
"spam"
:
[
"abcde"
]},
},
"extras"
:
{
"feature_bar"
:
[
"bar"
]},
}
)
set_package_requires
(
poetry
)
exporter
=
Exporter
(
poetry
)
exporter
.
export
(
"requirements.txt"
,
Path
(
tmp_dir
),
"requirements.txt"
,
dev
=
True
,
with_hashes
=
False
,
extras
=
extras
,
)
with
(
Path
(
tmp_dir
)
/
"requirements.txt"
)
.
open
(
encoding
=
"utf-8"
)
as
f
:
content
=
f
.
read
()
expected
=
"
\n
"
.
join
(
lines
)
assert
content
.
strip
()
==
expected
def
test_exporter_can_export_requirements_txt_with_git_packages
(
tmp_dir
:
str
,
poetry
:
Poetry
):
poetry
.
locker
.
mock_lock_data
(
{
"package"
:
[
{
"name"
:
"foo"
,
"version"
:
"1.2.3"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"source"
:
{
"type"
:
"git"
,
"url"
:
"https://github.com/foo/foo.git"
,
"reference"
:
"123456"
,
},
}
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"foo"
:
[]},
},
}
)
set_package_requires
(
poetry
)
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
=
"""
\
foo @ git+https://github.com/foo/foo.git@123456 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
"""
assert
content
==
expected
def
test_exporter_can_export_requirements_txt_with_nested_packages
(
tmp_dir
:
str
,
poetry
:
Poetry
):
poetry
.
locker
.
mock_lock_data
(
{
"package"
:
[
{
"name"
:
"foo"
,
"version"
:
"1.2.3"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"source"
:
{
"type"
:
"git"
,
"url"
:
"https://github.com/foo/foo.git"
,
"reference"
:
"123456"
,
},
},
{
"name"
:
"bar"
,
"version"
:
"4.5.6"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"dependencies"
:
{
"foo"
:
"rev 123456"
},
},
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"foo"
:
[],
"bar"
:
[]},
},
}
)
set_package_requires
(
poetry
,
skip
=
{
"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
=
"""
\
bar==4.5.6 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
foo @ git+https://github.com/foo/foo.git@123456 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
"""
assert
content
==
expected
def
test_exporter_can_export_requirements_txt_with_nested_packages_cyclic
(
tmp_dir
:
str
,
poetry
:
Poetry
):
poetry
.
locker
.
mock_lock_data
(
{
"package"
:
[
{
"name"
:
"foo"
,
"version"
:
"1.2.3"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"dependencies"
:
{
"bar"
:
{
"version"
:
"4.5.6"
}},
},
{
"name"
:
"bar"
,
"version"
:
"4.5.6"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"dependencies"
:
{
"baz"
:
{
"version"
:
"7.8.9"
}},
},
{
"name"
:
"baz"
,
"version"
:
"7.8.9"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"dependencies"
:
{
"foo"
:
{
"version"
:
"1.2.3"
}},
},
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"foo"
:
[],
"bar"
:
[],
"baz"
:
[]},
},
}
)
set_package_requires
(
poetry
,
skip
=
{
"bar"
,
"baz"
})
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 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
baz==7.8.9 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
foo==1.2.3 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
"""
assert
content
==
expected
def
test_exporter_can_export_requirements_txt_with_nested_packages_and_multiple_markers
(
tmp_dir
:
str
,
poetry
:
Poetry
):
poetry
.
locker
.
mock_lock_data
(
{
"package"
:
[
{
"name"
:
"foo"
,
"version"
:
"1.2.3"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"dependencies"
:
{
"bar"
:
[
{
"version"
:
">=1.2.3,<7.8.10"
,
"markers"
:
'platform_system != "Windows"'
,
},
{
"version"
:
">=4.5.6,<7.8.10"
,
"markers"
:
'platform_system == "Windows"'
,
},
]
},
},
{
"name"
:
"bar"
,
"version"
:
"7.8.9"
,
"category"
:
"main"
,
"optional"
:
True
,
"python-versions"
:
"*"
,
"dependencies"
:
{
"baz"
:
{
"version"
:
"!=10.11.12"
,
"markers"
:
'platform_system == "Windows"'
,
}
},
},
{
"name"
:
"baz"
,
"version"
:
"10.11.13"
,
"category"
:
"main"
,
"optional"
:
True
,
"python-versions"
:
"*"
,
},
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"foo"
:
[],
"bar"
:
[],
"baz"
:
[]},
},
}
)
set_package_requires
(
poetry
)
exporter
=
Exporter
(
poetry
)
exporter
.
export
(
"requirements.txt"
,
Path
(
tmp_dir
),
"requirements.txt"
,
with_hashes
=
False
)
with
(
Path
(
tmp_dir
)
/
"requirements.txt"
)
.
open
(
encoding
=
"utf-8"
)
as
f
:
content
=
f
.
read
()
expected
=
"""
\
bar==7.8.9 ;
\
python_version >= "2.7" and python_version < "2.8" and platform_system != "Windows" or
\
python_version >= "3.6" and python_version < "4.0" and platform_system != "Windows" or
\
python_version >= "2.7" and python_version < "2.8" and platform_system == "Windows" or
\
python_version >= "3.6" and python_version < "4.0" and platform_system == "Windows"
baz==10.11.13 ;
\
python_version >= "2.7" and python_version < "2.8" and platform_system == "Windows" or
\
python_version >= "3.6" and python_version < "4.0" and platform_system == "Windows"
foo==1.2.3 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
"""
assert
content
==
expected
def
test_exporter_can_export_requirements_txt_with_git_packages_and_markers
(
tmp_dir
:
str
,
poetry
:
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"
:
"git"
,
"url"
:
"https://github.com/foo/foo.git"
,
"reference"
:
"123456"
,
},
}
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"foo"
:
[]},
},
}
)
set_package_requires
(
poetry
)
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
=
"""
\
foo @ git+https://github.com/foo/foo.git@123456 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "3.7"
"""
assert
content
==
expected
def
test_exporter_can_export_requirements_txt_with_directory_packages
(
tmp_dir
:
str
,
poetry
:
Poetry
,
working_directory
:
Path
):
poetry
.
locker
.
mock_lock_data
(
{
"package"
:
[
{
"name"
:
"foo"
,
"version"
:
"1.2.3"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"source"
:
{
"type"
:
"directory"
,
"url"
:
"tests/fixtures/sample_project"
,
"reference"
:
""
,
},
}
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"foo"
:
[]},
},
}
)
set_package_requires
(
poetry
)
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
=
f
"""
\
foo @ {working_directory.as_uri()}/tests/fixtures/sample_project ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
"""
assert
content
==
expected
def
test_exporter_can_export_requirements_txt_with_nested_directory_packages
(
tmp_dir
:
str
,
poetry
:
Poetry
,
working_directory
:
Path
):
poetry
.
locker
.
mock_lock_data
(
{
"package"
:
[
{
"name"
:
"foo"
,
"version"
:
"1.2.3"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"source"
:
{
"type"
:
"directory"
,
"url"
:
"tests/fixtures/sample_project"
,
"reference"
:
""
,
},
},
{
"name"
:
"bar"
,
"version"
:
"4.5.6"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"source"
:
{
"type"
:
"directory"
,
"url"
:
"tests/fixtures/sample_project/../project_with_nested_local/bar"
,
# noqa: E501
"reference"
:
""
,
},
},
{
"name"
:
"baz"
,
"version"
:
"7.8.9"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"source"
:
{
"type"
:
"directory"
,
"url"
:
"tests/fixtures/sample_project/../project_with_nested_local/bar/.."
,
# noqa: E501
"reference"
:
""
,
},
},
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"foo"
:
[],
"bar"
:
[],
"baz"
:
[]},
},
}
)
set_package_requires
(
poetry
)
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
=
f
"""
\
bar @ {working_directory.as_uri()}/tests/fixtures/project_with_nested_local/bar ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
baz @ {working_directory.as_uri()}/tests/fixtures/project_with_nested_local ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
foo @ {working_directory.as_uri()}/tests/fixtures/sample_project ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
"""
assert
content
==
expected
def
test_exporter_can_export_requirements_txt_with_directory_packages_and_markers
(
tmp_dir
:
str
,
poetry
:
Poetry
,
working_directory
:
Path
):
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"
:
[]},
},
}
)
set_package_requires
(
poetry
)
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
=
f
"""
\
foo @ {working_directory.as_uri()}/tests/fixtures/sample_project ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "3.7"
"""
assert
content
==
expected
def
test_exporter_can_export_requirements_txt_with_file_packages
(
tmp_dir
:
str
,
poetry
:
Poetry
,
working_directory
:
Path
):
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"
:
[]},
},
}
)
set_package_requires
(
poetry
)
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
=
f
"""
\
foo @ {working_directory.as_uri()}/tests/fixtures/distributions/demo-0.1.0.tar.gz ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
"""
assert
content
==
expected
def
test_exporter_can_export_requirements_txt_with_file_packages_and_markers
(
tmp_dir
:
str
,
poetry
:
Poetry
,
working_directory
:
Path
):
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"
:
[]},
},
}
)
set_package_requires
(
poetry
)
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
=
f
"""
\
foo @ {working_directory.as_uri()}/tests/fixtures/distributions/demo-0.1.0.tar.gz ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "3.7"
"""
assert
content
==
expected
def
test_exporter_exports_requirements_txt_with_legacy_packages
(
tmp_dir
:
str
,
poetry
:
Poetry
):
poetry
.
pool
.
add_repository
(
LegacyRepository
(
"custom"
,
"https://example.com/simple"
,
)
)
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"
]},
},
}
)
set_package_requires
(
poetry
)
exporter
=
Exporter
(
poetry
)
exporter
.
export
(
"requirements.txt"
,
Path
(
tmp_dir
),
"requirements.txt"
,
dev
=
True
)
with
(
Path
(
tmp_dir
)
/
"requirements.txt"
)
.
open
(
encoding
=
"utf-8"
)
as
f
:
content
=
f
.
read
()
expected
=
"""
\
--extra-index-url https://example.com/simple
bar==4.5.6 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
\\
--hash=sha256:67890
foo==1.2.3 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
\\
--hash=sha256:12345
"""
assert
content
==
expected
def
test_exporter_exports_requirements_txt_with_url_false
(
tmp_dir
:
str
,
poetry
:
Poetry
):
poetry
.
pool
.
add_repository
(
LegacyRepository
(
"custom"
,
"https://example.com/simple"
,
)
)
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"
]},
},
}
)
set_package_requires
(
poetry
)
exporter
=
Exporter
(
poetry
)
exporter
.
export
(
"requirements.txt"
,
Path
(
tmp_dir
),
"requirements.txt"
,
dev
=
True
,
with_urls
=
False
)
with
(
Path
(
tmp_dir
)
/
"requirements.txt"
)
.
open
(
encoding
=
"utf-8"
)
as
f
:
content
=
f
.
read
()
expected
=
"""
\
bar==4.5.6 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
\\
--hash=sha256:67890
foo==1.2.3 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
\\
--hash=sha256:12345
"""
assert
content
==
expected
def
test_exporter_exports_requirements_txt_with_legacy_packages_trusted_host
(
tmp_dir
:
str
,
poetry
:
Poetry
):
poetry
.
pool
.
add_repository
(
LegacyRepository
(
"custom"
,
"http://example.com/simple"
,
)
)
poetry
.
locker
.
mock_lock_data
(
{
"package"
:
[
{
"name"
:
"bar"
,
"version"
:
"4.5.6"
,
"category"
:
"dev"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"source"
:
{
"type"
:
"legacy"
,
"url"
:
"http://example.com/simple"
,
"reference"
:
""
,
},
},
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"bar"
:
[
"67890"
]},
},
}
)
set_package_requires
(
poetry
)
exporter
=
Exporter
(
poetry
)
exporter
.
export
(
"requirements.txt"
,
Path
(
tmp_dir
),
"requirements.txt"
,
dev
=
True
)
with
(
Path
(
tmp_dir
)
/
"requirements.txt"
)
.
open
(
encoding
=
"utf-8"
)
as
f
:
content
=
f
.
read
()
expected
=
"""
\
--trusted-host example.com
--extra-index-url http://example.com/simple
bar==4.5.6 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
\\
--hash=sha256:67890
"""
assert
content
==
expected
@pytest.mark.parametrize
(
[
"dev"
,
"expected"
],
[
(
True
,
[
'bar==1.2.2 ; python_version >= "2.7" and python_version < "2.8" or'
' python_version >= "3.6" and python_version < "4.0"'
,
'baz==1.2.3 ; python_version >= "2.7" and python_version < "2.8" or'
' python_version >= "3.6" and python_version < "4.0"'
,
'foo==1.2.1 ; python_version >= "2.7" and python_version < "2.8" or'
' python_version >= "3.6" and python_version < "4.0"'
,
],
),
(
False
,
[
'bar==1.2.2 ; python_version >= "2.7" and python_version < "2.8" or'
' python_version >= "3.6" and python_version < "4.0"'
,
'foo==1.2.1 ; python_version >= "2.7" and python_version < "2.8" or'
' python_version >= "3.6" and python_version < "4.0"'
,
],
),
],
)
def
test_exporter_exports_requirements_txt_with_dev_extras
(
tmp_dir
:
str
,
poetry
:
Poetry
,
dev
:
bool
,
expected
:
list
[
str
]
):
poetry
.
locker
.
mock_lock_data
(
{
"package"
:
[
{
"name"
:
"foo"
,
"version"
:
"1.2.1"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
},
{
"name"
:
"bar"
,
"version"
:
"1.2.2"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"dependencies"
:
{
"baz"
:
{
"version"
:
">=0.1.0"
,
"optional"
:
True
,
"markers"
:
"extra == 'baz'"
,
}
},
"extras"
:
{
"baz"
:
[
"baz (>=0.1.0)"
]},
},
{
"name"
:
"baz"
,
"version"
:
"1.2.3"
,
"category"
:
"dev"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
},
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"foo"
:
[],
"bar"
:
[],
"baz"
:
[]},
},
}
)
set_package_requires
(
poetry
)
exporter
=
Exporter
(
poetry
)
exporter
.
export
(
"requirements.txt"
,
Path
(
tmp_dir
),
"requirements.txt"
,
dev
=
dev
)
with
(
Path
(
tmp_dir
)
/
"requirements.txt"
)
.
open
(
encoding
=
"utf-8"
)
as
f
:
content
=
f
.
read
()
assert
content
==
"
\n
"
.
join
(
expected
)
+
"
\n
"
def
test_exporter_exports_requirements_txt_with_legacy_packages_and_duplicate_sources
(
tmp_dir
:
str
,
poetry
:
Poetry
):
poetry
.
pool
.
add_repository
(
LegacyRepository
(
"custom"
,
"https://example.com/simple"
,
)
)
poetry
.
pool
.
add_repository
(
LegacyRepository
(
"custom"
,
"https://foobaz.com/simple"
,
)
)
poetry
.
locker
.
mock_lock_data
(
{
"package"
:
[
{
"name"
:
"foo"
,
"version"
:
"1.2.3"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"source"
:
{
"type"
:
"legacy"
,
"url"
:
"https://example.com/simple"
,
"reference"
:
""
,
},
},
{
"name"
:
"bar"
,
"version"
:
"4.5.6"
,
"category"
:
"dev"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"source"
:
{
"type"
:
"legacy"
,
"url"
:
"https://example.com/simple"
,
"reference"
:
""
,
},
},
{
"name"
:
"baz"
,
"version"
:
"7.8.9"
,
"category"
:
"dev"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"source"
:
{
"type"
:
"legacy"
,
"url"
:
"https://foobaz.com/simple"
,
"reference"
:
""
,
},
},
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"foo"
:
[
"12345"
],
"bar"
:
[
"67890"
],
"baz"
:
[
"24680"
]},
},
}
)
set_package_requires
(
poetry
)
exporter
=
Exporter
(
poetry
)
exporter
.
export
(
"requirements.txt"
,
Path
(
tmp_dir
),
"requirements.txt"
,
dev
=
True
)
with
(
Path
(
tmp_dir
)
/
"requirements.txt"
)
.
open
(
encoding
=
"utf-8"
)
as
f
:
content
=
f
.
read
()
expected
=
"""
\
--extra-index-url https://example.com/simple
--extra-index-url https://foobaz.com/simple
bar==4.5.6 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
\\
--hash=sha256:67890
baz==7.8.9 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
\\
--hash=sha256:24680
foo==1.2.3 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
\\
--hash=sha256:12345
"""
assert
content
==
expected
def
test_exporter_exports_requirements_txt_with_legacy_packages_and_credentials
(
tmp_dir
:
str
,
poetry
:
Poetry
,
config
:
Config
):
poetry
.
config
.
merge
(
{
"repositories"
:
{
"custom"
:
{
"url"
:
"https://example.com/simple"
}},
"http-basic"
:
{
"custom"
:
{
"username"
:
"foo"
,
"password"
:
"bar"
}},
}
)
poetry
.
pool
.
add_repository
(
LegacyRepository
(
"custom"
,
"https://example.com/simple"
,
config
=
poetry
.
config
)
)
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"
]},
},
}
)
set_package_requires
(
poetry
)
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 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
\\
--hash=sha256:67890
foo==1.2.3 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
\\
--hash=sha256:12345
"""
assert
content
==
expected
def
test_exporter_exports_requirements_txt_to_standard_output
(
tmp_dir
:
str
,
poetry
:
Poetry
,
capsys
:
CaptureFixture
):
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"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
},
],
"metadata"
:
{
"python-versions"
:
"*"
,
"content-hash"
:
"123456789"
,
"hashes"
:
{
"foo"
:
[],
"bar"
:
[]},
},
}
)
set_package_requires
(
poetry
)
exporter
=
Exporter
(
poetry
)
exporter
.
export
(
"requirements.txt"
,
Path
(
tmp_dir
),
sys
.
stdout
)
out
,
err
=
capsys
.
readouterr
()
expected
=
"""
\
bar==4.5.6 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
foo==1.2.3 ;
\
python_version >= "2.7" and python_version < "2.8" or
\
python_version >= "3.6" and python_version < "4.0"
"""
assert
out
==
expected
def
test_exporter_doesnt_confuse_repeated_packages
(
tmp_dir
:
str
,
poetry
:
Poetry
,
capsys
:
CaptureFixture
):
# Testcase derived from <https://github.com/python-poetry/poetry/issues/5141>.
poetry
.
locker
.
mock_lock_data
(
{
"package"
:
[
{
"name"
:
"celery"
,
"version"
:
"5.1.2"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"<3.7"
,
"dependencies"
:
{
"click"
:
">=7.0,<8.0"
,
"click-didyoumean"
:
">=0.0.3"
,
"click-plugins"
:
">=1.1.1"
,
},
},
{
"name"
:
"celery"
,
"version"
:
"5.2.3"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
">=3.7"
,
"dependencies"
:
{
"click"
:
">=8.0.3,<9.0"
,
"click-didyoumean"
:
">=0.0.3"
,
"click-plugins"
:
">=1.1.1"
,
},
},
{
"name"
:
"click"
,
"version"
:
"7.1.2"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
(
">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
),
},
{
"name"
:
"click"
,
"version"
:
"8.0.3"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
">=3.6"
,
"dependencies"
:
{},
},
{
"name"
:
"click-didyoumean"
,
"version"
:
"0.0.3"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"dependencies"
:
{
"click"
:
"*"
},
},
{
"name"
:
"click-didyoumean"
,
"version"
:
"0.3.0"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
">=3.6.2,<4.0.0"
,
"dependencies"
:
{
"click"
:
">=7"
},
},
{
"name"
:
"click-plugins"
,
"version"
:
"1.1.1"
,
"category"
:
"main"
,
"optional"
:
False
,
"python-versions"
:
"*"
,
"dependencies"
:
{
"click"
:
">=4.0"
},
},
],
"metadata"
:
{
"lock-version"
:
"1.1"
,
"python-versions"
:
"^3.6"
,
"content-hash"
:
(
"832b13a88e5020c27cbcd95faa577bf0dbf054a65c023b45dc9442b640d414e6"
),
"hashes"
:
{
"celery"
:
[],
"click-didyoumean"
:
[],
"click-plugins"
:
[],
"click"
:
[],
},
},
}
)
root
=
poetry
.
package
.
with_dependency_groups
([],
only
=
True
)
root
.
python_versions
=
"^3.6"
root
.
add_dependency
(
Factory
.
create_dependency
(
name
=
"celery"
,
constraint
=
{
"version"
:
"5.1.2"
,
"python"
:
"<3.7"
}
)
)
root
.
add_dependency
(
Factory
.
create_dependency
(
name
=
"celery"
,
constraint
=
{
"version"
:
"5.2.3"
,
"python"
:
">=3.7"
}
)
)
poetry
.
_package
=
root
exporter
=
Exporter
(
poetry
)
exporter
.
export
(
"requirements.txt"
,
Path
(
tmp_dir
),
sys
.
stdout
)
out
,
err
=
capsys
.
readouterr
()
expected
=
"""
\
celery==5.1.2 ; python_version >= "3.6" and python_version < "3.7"
celery==5.2.3 ; python_version >= "3.7" and python_version < "4.0"
click-didyoumean==0.0.3 ; python_version >= "3.6" and python_version < "3.7"
click-didyoumean==0.3.0 ; python_version >= "3.7" and python_full_version < "4.0.0"
click-plugins==1.1.1 ;
\
python_version >= "3.6" and python_version < "3.7" or
\
python_version >= "3.7" and python_version < "4.0"
click==7.1.2 ; python_version >= "3.6" and python_version < "3.7"
click==8.0.3 ;
\
python_version >= "3.7" and python_version < "4.0" or
\
python_version >= "3.7" and python_full_version < "4.0.0"
"""
assert
out
==
expected
def
test_exporter_handles_extras_next_to_non_extras
(
tmp_dir
:
str
,
poetry
:
Poetry
,
capsys
:
CaptureFixture
):
# Testcase similar to the solver testcase added at #5305.
poetry
.
locker
.
mock_lock_data
(
{
"package"
:
[
{
"name"
:
"localstack"
,
"python-versions"
:
"*"
,
"version"
:
"1.0.0"
,
"category"
:
"main"
,
"optional"
:
False
,
"dependencies"
:
{
"localstack-ext"
:
[
{
"version"
:
">=1.0.0"
},
{
"version"
:
">=1.0.0"
,
"extras"
:
[
"bar"
],
"markers"
:
'extra == "foo"'
,
},
]
},
"extras"
:
{
"foo"
:
[
"localstack-ext (>=1.0.0)"
]},
},
{
"name"
:
"localstack-ext"
,
"python-versions"
:
"*"
,
"version"
:
"1.0.0"
,
"category"
:
"main"
,
"optional"
:
False
,
"dependencies"
:
{
"something"
:
"*"
,
"something-else"
:
{
"version"
:
">=1.0.0"
,
"markers"
:
'extra == "bar"'
,
},
"another-thing"
:
{
"version"
:
">=1.0.0"
,
"markers"
:
'extra == "baz"'
,
},
},
"extras"
:
{
"bar"
:
[
"something-else (>=1.0.0)"
],
"baz"
:
[
"another-thing (>=1.0.0)"
],
},
},
{
"name"
:
"something"
,
"python-versions"
:
"*"
,
"version"
:
"1.0.0"
,
"category"
:
"main"
,
"optional"
:
False
,
"dependencies"
:
{},
},
{
"name"
:
"something-else"
,
"python-versions"
:
"*"
,
"version"
:
"1.0.0"
,
"category"
:
"main"
,
"optional"
:
False
,
"dependencies"
:
{},
},
{
"name"
:
"another-thing"
,
"python-versions"
:
"*"
,
"version"
:
"1.0.0"
,
"category"
:
"main"
,
"optional"
:
False
,
"dependencies"
:
{},
},
],
"metadata"
:
{
"lock-version"
:
"1.1"
,
"python-versions"
:
"^3.6"
,
"content-hash"
:
(
"832b13a88e5020c27cbcd95faa577bf0dbf054a65c023b45dc9442b640d414e6"
),
"hashes"
:
{
"localstack"
:
[],
"localstack-ext"
:
[],
"something"
:
[],
"something-else"
:
[],
"another-thing"
:
[],
},
},
}
)
root
=
poetry
.
package
.
with_dependency_groups
([],
only
=
True
)
root
.
python_versions
=
"^3.6"
root
.
add_dependency
(
Factory
.
create_dependency
(
name
=
"localstack"
,
constraint
=
{
"version"
:
"^1.0.0"
,
"extras"
:
[
"foo"
]}
)
)
poetry
.
_package
=
root
exporter
=
Exporter
(
poetry
)
exporter
.
export
(
"requirements.txt"
,
Path
(
tmp_dir
),
sys
.
stdout
)
out
,
err
=
capsys
.
readouterr
()
expected
=
"""
\
localstack-ext==1.0.0 ; python_version >= "3.6" and python_version < "4.0"
localstack==1.0.0 ; python_version >= "3.6" and python_version < "4.0"
something-else==1.0.0 ; python_version >= "3.6" and python_version < "4.0"
something==1.0.0 ; python_version >= "3.6" and python_version < "4.0"
"""
assert
out
==
expected
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment