Files
pipenv/tests/integration/test_requirements.py
Matt Davis 6ac1451ec8 stop using requirementslib models (#5793)
* Move away from requirementslib models

* Revise test since PEP-440 does not support wildcard versions but does support equivalent compatible release specifiers.

* simplify and remove dead code

* Ensure the os_name marker is AND with the other markers.

* Move what we still need from requirementslib into the pipenv utils and stop vendoring it.

* Remove requirementslib.

* force upgrade of virtualenv for python 3.12

* remove virtualenv-clone

* Update vcs specifiers documentation; infer name from specific pip line formats where possible.

* Provide helpful text and error for recently removed commands

* Set the right log levels and verbosity to show users the errors generated by pip resolver when supplying -v flag

* Fix the collection of all matching package hashes for non-pypi indexes.  Plus lesson from testing torch which contains local identifiers.
2023-08-19 16:36:52 -04:00

301 lines
9.8 KiB
Python

import json
import os
import pytest
from pipenv.utils.shell import temp_environ
from pipenv.utils.requirements import requirements_from_lockfile
@pytest.mark.requirements
def test_requirements_generates_requirements_from_lockfile(pipenv_instance_pypi):
with pipenv_instance_pypi() as p:
packages = ('requests', '2.14.0')
dev_packages = ('flask', '0.12.2')
with open(p.pipfile_path, 'w') as f:
contents = f"""
[packages]
{packages[0]}= "=={packages[1]}"
[dev-packages]
{dev_packages[0]}= "=={dev_packages[1]}"
""".strip()
f.write(contents)
p.pipenv('lock')
c = p.pipenv('requirements')
assert c.returncode == 0
assert f'{packages[0]}=={packages[1]}' in c.stdout
assert f'{dev_packages[0]}=={dev_packages[1]}' not in c.stdout
d = p.pipenv('requirements --dev')
assert d.returncode == 0
assert f'{packages[0]}=={packages[1]}' in d.stdout
assert f'{dev_packages[0]}=={dev_packages[1]}' in d.stdout
e = p.pipenv('requirements --dev-only')
assert e.returncode == 0
assert f'{packages[0]}=={packages[1]}' not in e.stdout
assert f'{dev_packages[0]}=={dev_packages[1]}' in e.stdout
e = p.pipenv('requirements --hash')
assert e.returncode == 0
assert f'{packages[0]}=={packages[1]}' in e.stdout
for value in p.lockfile['default'].values():
for hash in value['hashes']:
assert f' --hash={hash}' in e.stdout
@pytest.mark.requirements
def test_requirements_generates_requirements_from_lockfile_multiple_sources(pipenv_instance_private_pypi):
with pipenv_instance_private_pypi() as p:
packages = ('six', '1.12.0')
dev_packages = ('itsdangerous', '1.1.0')
with open(p.pipfile_path, 'w') as f:
contents = f"""
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[[source]]
name = "other_source"
url = "https://some_other_source.org"
verify_ssl = true
[packages]
{packages[0]}= "=={packages[1]}"
[dev-packages]
{dev_packages[0]}= "=={dev_packages[1]}"
""".strip()
f.write(contents)
l = p.pipenv('lock')
assert l.returncode == 0
c = p.pipenv('requirements')
assert c.returncode == 0
assert '-i https://pypi.org/simple' in c.stdout
assert '--extra-index-url https://some_other_source.org' in c.stdout
@pytest.mark.requirements
def test_requirements_generates_requirements_from_lockfile_from_categories(pipenv_instance_private_pypi):
with pipenv_instance_private_pypi() as p:
packages = ('six', '1.12.0')
dev_packages = ('itsdangerous', '1.1.0')
test_packages = ('pytest', '7.1.3')
doc_packages = ('docutils', '0.19')
with open(p.pipfile_path, 'w') as f:
contents = f"""
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[packages]
{packages[0]}= "=={packages[1]}"
[dev-packages]
{dev_packages[0]}= "=={dev_packages[1]}"
[test]
{test_packages[0]}= "=={test_packages[1]}"
[doc]
{doc_packages[0]}= "=={doc_packages[1]}"
""".strip()
f.write(contents)
l = p.pipenv('lock')
assert l.returncode == 0
c = p.pipenv('requirements --dev-only')
assert c.returncode == 0
assert f'{packages[0]}=={packages[1]}' not in c.stdout
assert f'{test_packages[0]}=={test_packages[1]}' not in c.stdout
assert f'{doc_packages[0]}=={doc_packages[1]}' not in c.stdout
assert f'{dev_packages[0]}=={dev_packages[1]}' in c.stdout
d = p.pipenv('requirements --categories="test, doc"')
assert d.returncode == 0
assert f'{packages[0]}=={packages[1]}' not in d.stdout
assert f'{dev_packages[0]}=={dev_packages[1]}' not in d.stdout
assert f'{test_packages[0]}=={test_packages[1]}' in d.stdout
assert f'{doc_packages[0]}=={doc_packages[1]}' in d.stdout
@pytest.mark.requirements
def test_requirements_with_git_requirements(pipenv_instance_pypi):
req_hash = '3264a0046e1aa3c0a813335286ebdbc651f58b13'
lockfile = {
"_meta": {"sources": []},
"default": {
"dataclasses-json": {
"editable": True,
"git": "https://github.com/lidatong/dataclasses-json.git",
"ref": req_hash
}
},
"develop": {}
}
with pipenv_instance_pypi() as p:
with open(p.lockfile_path, 'w') as f:
json.dump(lockfile, f)
c = p.pipenv('requirements')
assert c.returncode == 0
assert "dataclasses-json" in c.stdout
assert req_hash in c.stdout
@pytest.mark.requirements
def test_requirements_markers_get_included(pipenv_instance_pypi):
package, version, markers = "werkzeug", "==2.1.2", "python_version >= '3.7'"
lockfile = {
"_meta": {"sources": []},
"default": {
package: {
"hashes": [
"sha256:1ce08e8093ed67d638d63879fd1ba3735817f7a80de3674d293f5984f25fb6e6",
"sha256:72a4b735692dd3135217911cbeaa1be5fa3f62bffb8745c5215420a03dc55255"
],
"markers": markers,
"version": version
}
},
"develop": {}
}
with pipenv_instance_pypi() as p:
with open(p.lockfile_path, 'w') as f:
json.dump(lockfile, f)
c = p.pipenv('requirements')
assert c.returncode == 0
assert f'{package}{version}; {markers}' in c.stdout
@pytest.mark.requirements
def test_requirements_markers_get_excluded(pipenv_instance_pypi):
package, version, markers = "werkzeug", "==2.1.2", "python_version >= '3.7'"
lockfile = {
"_meta": {"sources": []},
"default": {
package: {
"hashes": [
"sha256:1ce08e8093ed67d638d63879fd1ba3735817f7a80de3674d293f5984f25fb6e6",
"sha256:72a4b735692dd3135217911cbeaa1be5fa3f62bffb8745c5215420a03dc55255"
],
"markers": markers,
"version": version
}
},
"develop": {}
}
with pipenv_instance_pypi() as p:
with open(p.lockfile_path, 'w') as f:
json.dump(lockfile, f)
c = p.pipenv('requirements --exclude-markers')
assert c.returncode == 0
assert markers not in c.stdout
@pytest.mark.requirements
def test_requirements_hashes_get_included(pipenv_instance_pypi):
package, version, markers = "werkzeug", "==2.1.2", "python_version >= '3.7'"
first_hash = "sha256:1ce08e8093ed67d638d63879fd1ba3735817f7a80de3674d293f5984f25fb6e6"
second_hash = "sha256:72a4b735692dd3135217911cbeaa1be5fa3f62bffb8745c5215420a03dc55255"
lockfile = {
"_meta": {"sources": []},
"default": {
package: {
"hashes": [
first_hash,
second_hash
],
"markers": markers,
"version": version
}
},
"develop": {}
}
with pipenv_instance_pypi() as p:
with open(p.lockfile_path, 'w') as f:
json.dump(lockfile, f)
c = p.pipenv('requirements --hash')
assert c.returncode == 0
assert f'{package}{version}; {markers} --hash={first_hash} --hash={second_hash}' in c.stdout
def test_requirements_generates_requirements_from_lockfile_without_env_var_expansion(
pipenv_instance_pypi,
):
lockfile = {
"_meta": {
"sources": [
{
"name": "private_source",
"url": "https://${redacted_user}:${redacted_pwd}@private_source.org",
"verify_ssl": True,
}
]
},
"default": {},
}
with pipenv_instance_pypi() as p:
with open(p.lockfile_path, "w") as f:
json.dump(lockfile, f)
with temp_environ():
os.environ['redacted_user'] = "example_user"
os.environ['redacted_pwd'] = "example_pwd"
c = p.pipenv("requirements")
assert c.returncode == 0
assert (
"-i https://${redacted_user}:${redacted_pwd}@private_source.org"
in c.stdout
)
@pytest.mark.requirements
@pytest.mark.parametrize(
"deps, include_hashes, include_markers, expected",
[
(
{
"django-storages": {
"version": "==1.12.3",
"extras": ["azure"]
}
},
True,
True,
["django-storages[azure]==1.12.3"]
),
(
{
"evotum-cripto": {
"file": "https://gitlab.com/eVotUM/Cripto-py/-/archive/develop/Cripto-py-develop.zip"
}
},
True,
True,
["https://gitlab.com/eVotUM/Cripto-py/-/archive/develop/Cripto-py-develop.zip"]
),
(
{
"pyjwt": {
"git": "https://github.com/jpadilla/pyjwt.git",
"ref": "7665aa625506a11bae50b56d3e04413a3dc6fdf8",
"extras": ["crypto"]
}
},
True,
True,
["pyjwt[crypto]@ git+https://github.com/jpadilla/pyjwt.git@7665aa625506a11bae50b56d3e04413a3dc6fdf8"]
)
]
)
def test_requirements_from_deps(deps, include_hashes, include_markers, expected):
result = requirements_from_lockfile(deps, include_hashes, include_markers)
assert result == expected