From bd8c77c121880754179c328bb22d0ccb5054cd95 Mon Sep 17 00:00:00 2001 From: Till Grutschus Date: Mon, 20 Jun 2022 18:38:50 +0200 Subject: [PATCH 1/4] Do not expand env vars in requirements --- pipenv/cli/command.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pipenv/cli/command.py b/pipenv/cli/command.py index cc3a51133b..c884df5260 100644 --- a/pipenv/cli/command.py +++ b/pipenv/cli/command.py @@ -768,7 +768,7 @@ def requirements(state, dev=False, dev_only=False, hash=False): from pipenv.utils.dependencies import convert_deps_to_pip - lockfile = state.project.lockfile_content + lockfile = state.project.load_lockfile(expand_env_vars=False) for i, package_index in enumerate(lockfile["_meta"]["sources"]): prefix = "-i" if i == 0 else "--extra-index-url" From 802aea79e9cfe54289310b1a4b6673ba62b8e7f5 Mon Sep 17 00:00:00 2001 From: Till Grutschus Date: Mon, 20 Jun 2022 19:15:46 +0200 Subject: [PATCH 2/4] Test requirements env var expansion --- tests/integration/test_requirements.py | 103 +++++++++++++++++-------- 1 file changed, 71 insertions(+), 32 deletions(-) diff --git a/tests/integration/test_requirements.py b/tests/integration/test_requirements.py index 11aef3a441..a3a2b4ab22 100644 --- a/tests/integration/test_requirements.py +++ b/tests/integration/test_requirements.py @@ -1,13 +1,16 @@ import json +import os import pytest +from pipenv.utils.shell import temp_environ + @pytest.mark.requirements def test_requirements_generates_requirements_from_lockfile(PipenvInstance): with PipenvInstance(chdir=True) as p: - packages = ('requests', '2.14.0') - dev_packages = ('flask', '0.12.2') - with open(p.pipfile_path, 'w') as f: + 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]}" @@ -15,36 +18,38 @@ def test_requirements_generates_requirements_from_lockfile(PipenvInstance): {dev_packages[0]}= "=={dev_packages[1]}" """.strip() f.write(contents) - p.pipenv('lock') - c = p.pipenv('requirements') + 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 + 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') + 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 + 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') + 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 + 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') + 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 + 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(PipenvInstance): +def test_requirements_generates_requirements_from_lockfile_multiple_sources( + PipenvInstance, +): with PipenvInstance(chdir=True) as p: - packages = ('requests', '2.14.0') - dev_packages = ('flask', '0.12.2') - with open(p.pipfile_path, 'w') as f: + packages = ("requests", "2.14.0") + dev_packages = ("flask", "0.12.2") + with open(p.pipfile_path, "w") as f: contents = f""" [[source]] name = "pypi" @@ -60,34 +65,68 @@ def test_requirements_generates_requirements_from_lockfile_multiple_sources(Pipe {dev_packages[0]}= "=={dev_packages[1]}" """.strip() f.write(contents) - l = p.pipenv('lock') + l = p.pipenv("lock") assert l.returncode == 0 - c = p.pipenv('requirements') + 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 + 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_with_git_requirements(PipenvInstance): - req_name, req_hash = 'example-repo', 'cc858e89f19bc0dbd70983f86b811ab625dc9292' + req_name, req_hash = "example-repo", "cc858e89f19bc0dbd70983f86b811ab625dc9292" lockfile = { "_meta": {"sources": []}, "default": { req_name: { "editable": True, - "git": F"ssh://git@bitbucket.org/code/{req_name}.git", - "ref": req_hash + "git": f"ssh://git@bitbucket.org/code/{req_name}.git", + "ref": req_hash, } }, - "develop": {} + "develop": {}, } with PipenvInstance(chdir=True) as p: - with open(p.lockfile_path, 'w') as f: + with open(p.lockfile_path, "w") as f: json.dump(lockfile, f) - c = p.pipenv('requirements') + c = p.pipenv("requirements") assert c.returncode == 0 assert req_name in c.stdout assert req_hash in c.stdout + + +@pytest.mark.requirements +def test_requirements_generates_requirements_from_lockfile_without_env_var_expansion( + PipenvInstance, +): + lockfile = { + "_meta": { + "sources": [ + { + "name": "private_source", + "url": "https://${redacted_user}:${redacted_pwd}@private_source.org", + "verify_ssl": True, + } + ] + }, + "default": {}, + } + + with PipenvInstance(chdir=True) 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 + ) From f965f3395ec880a3ee903ab9aa92ff58bac9ba0d Mon Sep 17 00:00:00 2001 From: Till Grutschus Date: Mon, 20 Jun 2022 19:45:04 +0200 Subject: [PATCH 3/4] Wrote news --- news/5134.bugfix.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 news/5134.bugfix.rst diff --git a/news/5134.bugfix.rst b/news/5134.bugfix.rst new file mode 100644 index 0000000000..65a90f3e6f --- /dev/null +++ b/news/5134.bugfix.rst @@ -0,0 +1 @@ +Stopped expanding environment variables when using ``pipenv requirements`` From c36d54c200e843d853e4b7ea716c5bf5af43e7a0 Mon Sep 17 00:00:00 2001 From: Till Grutschus Date: Mon, 20 Jun 2022 19:58:55 +0200 Subject: [PATCH 4/4] Fix formatter screwup --- tests/integration/test_requirements.py | 67 ++++++++++++-------------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/tests/integration/test_requirements.py b/tests/integration/test_requirements.py index a3a2b4ab22..b58ca12c17 100644 --- a/tests/integration/test_requirements.py +++ b/tests/integration/test_requirements.py @@ -8,9 +8,9 @@ @pytest.mark.requirements def test_requirements_generates_requirements_from_lockfile(PipenvInstance): with PipenvInstance(chdir=True) as p: - packages = ("requests", "2.14.0") - dev_packages = ("flask", "0.12.2") - with open(p.pipfile_path, "w") as f: + 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]}" @@ -18,38 +18,36 @@ def test_requirements_generates_requirements_from_lockfile(PipenvInstance): {dev_packages[0]}= "=={dev_packages[1]}" """.strip() f.write(contents) - p.pipenv("lock") - c = p.pipenv("requirements") + 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 + 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") + 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 + 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") + 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 + 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") + 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 + 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( - PipenvInstance, -): +def test_requirements_generates_requirements_from_lockfile_multiple_sources(PipenvInstance): with PipenvInstance(chdir=True) as p: - packages = ("requests", "2.14.0") - dev_packages = ("flask", "0.12.2") - with open(p.pipfile_path, "w") as f: + packages = ('requests', '2.14.0') + dev_packages = ('flask', '0.12.2') + with open(p.pipfile_path, 'w') as f: contents = f""" [[source]] name = "pypi" @@ -65,35 +63,34 @@ def test_requirements_generates_requirements_from_lockfile_multiple_sources( {dev_packages[0]}= "=={dev_packages[1]}" """.strip() f.write(contents) - l = p.pipenv("lock") + l = p.pipenv('lock') assert l.returncode == 0 - c = p.pipenv("requirements") + 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 - + 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_with_git_requirements(PipenvInstance): - req_name, req_hash = "example-repo", "cc858e89f19bc0dbd70983f86b811ab625dc9292" + req_name, req_hash = 'example-repo', 'cc858e89f19bc0dbd70983f86b811ab625dc9292' lockfile = { "_meta": {"sources": []}, "default": { req_name: { "editable": True, - "git": f"ssh://git@bitbucket.org/code/{req_name}.git", - "ref": req_hash, + "git": F"ssh://git@bitbucket.org/code/{req_name}.git", + "ref": req_hash } }, - "develop": {}, + "develop": {} } with PipenvInstance(chdir=True) as p: - with open(p.lockfile_path, "w") as f: + with open(p.lockfile_path, 'w') as f: json.dump(lockfile, f) - c = p.pipenv("requirements") + c = p.pipenv('requirements') assert c.returncode == 0 assert req_name in c.stdout assert req_hash in c.stdout