From 034aa8129795275b2fa1169c459192ec50401b60 Mon Sep 17 00:00:00 2001 From: Matt Davis <=> Date: Fri, 11 Mar 2022 01:32:23 -0500 Subject: [PATCH 1/6] Ensure that dot env variables are actually in the real environment so they can be exapnded by os.path.expandvars --- pipenv/core.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/pipenv/core.py b/pipenv/core.py index 913c241a0a..f1b03c39eb 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -103,25 +103,23 @@ def load_dot_env(project, as_dict=False): [project_directory, ".env"] ) - if os.path.isfile(dotenv_file): + if not os.path.isfile(dotenv_file) and project.s.PIPENV_DOTENV_LOCATION: click.echo( - crayons.normal(fix_utf8("Loading .env environment variables..."), bold=True), + "{}: file {}={} does not exist!!\n{}".format( + crayons.red("Warning", bold=True), + crayons.normal("PIPENV_DOTENV_LOCATION", bold=True), + crayons.normal(project.s.PIPENV_DOTENV_LOCATION, bold=True), + crayons.red("Not loading environment variables.", bold=True), + ), err=True, ) - else: - if project.s.PIPENV_DOTENV_LOCATION: - click.echo( - "{}: file {}={} does not exist!!\n{}".format( - crayons.red("Warning", bold=True), - crayons.normal("PIPENV_DOTENV_LOCATION", bold=True), - crayons.normal(project.s.PIPENV_DOTENV_LOCATION, bold=True), - crayons.red("Not loading environment variables.", bold=True), - ), - err=True, - ) if as_dict: return dotenv.dotenv_values(dotenv_file) else: + click.echo( + crayons.normal(fix_utf8("Loading .env environment variables..."), bold=True), + err=True, + ) dotenv.load_dotenv(dotenv_file, override=True) project.s.initialize() @@ -2473,8 +2471,8 @@ def do_run(project, command, args, three=None, python=False, pypi_mirror=None): project, three=three, python=python, validate=False, pypi_mirror=pypi_mirror, ) + load_dot_env(project) env = os.environ.copy() - env.update(load_dot_env(project, as_dict=True) or {}) env.pop("PIP_SHIMS_BASE_MODULE", None) path = env.get('PATH', '') From e7732e2a1be5d054a20341ddef1115f8549e94b2 Mon Sep 17 00:00:00 2001 From: Matt Davis <=> Date: Fri, 11 Mar 2022 01:49:16 -0500 Subject: [PATCH 2/6] Add test case for this. --- tests/integration/test_cli.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/integration/test_cli.py b/tests/integration/test_cli.py index b2184b1f49..9aef70b119 100644 --- a/tests/integration/test_cli.py +++ b/tests/integration/test_cli.py @@ -210,6 +210,27 @@ def test_scripts(PipenvInstance): assert 'which python' in c.stdout +@pytest.mark.cli +def test_scripts_resolve_dot_env_vars(PipenvInstance): + with PipenvInstance() as p: + with open(".env", "w") as f: + contents = """ +HELLO=WORLD + """.strip() + f.write(contents) + + with open(p.pipfile_path, "w") as f: + contents = """ +[scripts] +hello = "echo $HELLO" + """.strip() + f.write(contents) + c = p.pipenv('run hello') + print(c) + print(c.stdout) + assert 'WORLD' in c.stdout + + @pytest.mark.cli def test_help(PipenvInstance): with PipenvInstance() as p: From 77a50e78e03058112a96cadaa08c5d7d0efde231 Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Fri, 11 Mar 2022 01:51:49 -0500 Subject: [PATCH 3/6] Add news fragment for 4975 and 3901 --- news/4975.bugfix.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 news/4975.bugfix.rst diff --git a/news/4975.bugfix.rst b/news/4975.bugfix.rst new file mode 100644 index 0000000000..ab0828741c --- /dev/null +++ b/news/4975.bugfix.rst @@ -0,0 +1 @@ +Environment variables from dot env files are now properly expanded when included in scripts. From 90a12ddb11bcd68f273b3a99053ff575b8ee7aa8 Mon Sep 17 00:00:00 2001 From: Matt Davis <=> Date: Fri, 11 Mar 2022 02:09:18 -0500 Subject: [PATCH 4/6] clean up edge case now that print success changed away from stderr. --- pipenv/core.py | 2 +- tests/integration/test_run.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pipenv/core.py b/pipenv/core.py index f1b03c39eb..e3c0bb2a86 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -118,7 +118,7 @@ def load_dot_env(project, as_dict=False): else: click.echo( crayons.normal(fix_utf8("Loading .env environment variables..."), bold=True), - err=True, + err=False, ) dotenv.load_dotenv(dotenv_file, override=True) project.s.initialize() diff --git a/tests/integration/test_run.py b/tests/integration/test_run.py index cf6a7f794a..fd224c6a1c 100644 --- a/tests/integration/test_run.py +++ b/tests/integration/test_run.py @@ -36,12 +36,12 @@ def test_scripts(PipenvInstance): assert c.returncode == 0 c = p.pipenv('run printfoo') assert c.returncode == 0 - assert c.stdout.splitlines()[0] == 'foo' + assert c.stdout.splitlines()[1] == 'foo' assert not c.stderr.strip() c = p.pipenv('run notfoundscript') assert c.returncode != 0 - assert c.stdout == '' + assert c.stdout == 'Loading .env environment variables...\n' if os.name != 'nt': # TODO: Implement this message for Windows. assert 'not found' in c.stderr @@ -60,7 +60,7 @@ def test_scripts(PipenvInstance): c = p.pipenv("run scriptwithenv") assert c.returncode == 0 if os.name != "nt": # This doesn't work on CI windows. - assert c.stdout.strip() == "WORLD" + assert c.stdout.splitlines()[1] == "WORLD" @pytest.mark.run From f4882737157b4edb8ebc01f23531eb99dd5c757c Mon Sep 17 00:00:00 2001 From: Matt Davis <=> Date: Fri, 11 Mar 2022 02:52:03 -0500 Subject: [PATCH 5/6] Adjust test stdout expectations. --- tests/integration/test_project.py | 4 ++-- tests/integration/test_run.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/integration/test_project.py b/tests/integration/test_project.py index 1ad60a2a13..f3d634078a 100644 --- a/tests/integration/test_project.py +++ b/tests/integration/test_project.py @@ -189,7 +189,7 @@ def test_run_in_virtualenv_with_global_context(PipenvInstance, virtualenv): c = p.pipenv("run python -c 'import click;print(click.__file__)'") assert c.returncode == 0, (c.stdout, c.stderr) - assert is_in_path(c.stdout.strip(), str(virtualenv)), (c.stdout.strip(), str(virtualenv)) + assert is_in_path(c.stdout.splitlines()[1], str(virtualenv)), (c.stdout.splitlines()[1], str(virtualenv)) c = p.pipenv("clean --dry-run") assert c.returncode == 0, (c.stdout, c.stderr) @@ -210,7 +210,7 @@ def test_run_in_virtualenv(PipenvInstance): assert c.returncode == 0 c = p.pipenv('run python -c "import click;print(click.__file__)"') assert c.returncode == 0 - assert normalize_path(c.stdout.strip()).startswith( + assert normalize_path(c.stdout.splitlines()[1]).startswith( normalize_path(str(project.virtualenv_location)) ) c = p.pipenv("clean --dry-run") diff --git a/tests/integration/test_run.py b/tests/integration/test_run.py index fd224c6a1c..a665b6a021 100644 --- a/tests/integration/test_run.py +++ b/tests/integration/test_run.py @@ -80,5 +80,5 @@ def test_run_with_usr_env_shebang(PipenvInstance): c = p.pipenv("run ./test_script") assert c.returncode == 0 project = Project() - lines = [line.strip() for line in c.stdout.splitlines()] + lines = [line.strip() for line in c.stdout.splitlines()[1:]] assert all(line == project.virtualenv_location for line in lines) From 5a151615aa47901f7c44e5b543fe2e2b0f6e9d24 Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Fri, 11 Mar 2022 03:25:13 -0500 Subject: [PATCH 6/6] missed these tests becasue they run only on earlier python versions. --- tests/integration/test_lock.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/test_lock.py b/tests/integration/test_lock.py index e1235f5401..2cd6220dbc 100644 --- a/tests/integration/test_lock.py +++ b/tests/integration/test_lock.py @@ -457,7 +457,7 @@ def test_outdated_setuptools_with_pep517_legacy_build_meta_is_updated(PipenvInst assert c.returncode == 0 c = p.pipenv("run python -c 'import setuptools; print(setuptools.__version__)'") assert c.returncode == 0 - assert c.stdout.strip() == "40.2.0" + assert c.stdout.splitlines()[1] == "40.2.0" c = p.pipenv("install legacy-backend-package") assert c.returncode == 0 assert "vistir" in p.lockfile["default"] @@ -481,7 +481,7 @@ def test_outdated_setuptools_with_pep517_cython_import_in_setuppy(PipenvInstance assert c.returncode == 0 c = p.pipenv("run python -c 'import setuptools; print(setuptools.__version__)'") assert c.returncode == 0 - assert c.stdout.strip() == "40.2.0" + assert c.stdout.splitlines()[1] == "40.2.0" c = p.pipenv("install cython-import-package") assert c.returncode == 0 assert "vistir" in p.lockfile["default"]