@@ -344,6 +344,68 @@ def test_file_option_expands_user(tmp_path, args, expected_stdout, expected_cont
344344 assert sorted (tmp_path .iterdir ()) == [home ]
345345
346346
347+ def make_command (directory : Path , name : str , output : str ) -> None :
348+ """
349+ Create a command named `name` in `directory` which prints `output`.
350+ """
351+
352+ if sys .platform == "win32" :
353+ (directory / f"{ name } .cmd" ).write_text (f"@echo { output } \n " )
354+ else :
355+ path = directory / name
356+ path .write_text (f"#!/bin/sh\n echo { output } \n " )
357+ path .chmod (0o755 )
358+
359+
360+ def test_run_with_path_from_env_file (tmp_path ):
361+ """
362+ Check that the command is looked up in the `PATH` set by the .env file.
363+ """
364+
365+ # We use two commands (one prints "x", the other "y").
366+ dotenv_bin_dir = tmp_path / "dotenv-bin"
367+ dotenv_bin_dir .mkdir ()
368+ make_command (directory = dotenv_bin_dir , name = "dotenv-test-command" , output = "x" )
369+ start_bin_dir = tmp_path / "start-bin"
370+ start_bin_dir .mkdir ()
371+ make_command (directory = start_bin_dir , name = "dotenv-test-command" , output = "y" )
372+ start_env = {
373+ ** os .environ ,
374+ "PATH" : os .pathsep .join ([str (start_bin_dir ), os .environ ["PATH" ]]),
375+ }
376+ # Unquoted, so that a Windows `PATH` ending with `\` isn't read as an escape.
377+ (tmp_path / ".env" ).write_text (f"PATH={ dotenv_bin_dir } { os .pathsep } ${{PATH}}" )
378+
379+ result = run_dotenv (["run" , "dotenv-test-command" ], cwd = tmp_path , env = start_env )
380+
381+ check_process (result , exit_code = 0 , stdout = "x\n " )
382+
383+
384+ @pytest .mark .skipif (sys .platform != "win32" , reason = "Windows-specific lookup" )
385+ def test_run_python_uses_path_on_windows (dotenv_path , tmp_path ):
386+ """
387+ Check that `dotenv run python` runs the first `python` in `PATH`, as with an
388+ activated virtual environment (#373).
389+
390+ A fake `python` placed first in `PATH` prints "x", while the real interpreter
391+ would run the `-c` code and print "y" instead. Without resolving the command
392+ against `PATH`, Windows picks the real interpreter.
393+ """
394+
395+ bin_dir = tmp_path / "bin"
396+ bin_dir .mkdir ()
397+ make_command (directory = bin_dir , name = "python" , output = "x" ) # Creates `python.cmd`.
398+ env = {** os .environ , "PATH" : os .pathsep .join ([str (bin_dir ), os .environ ["PATH" ]])}
399+
400+ result = run_dotenv (
401+ ["--file" , str (dotenv_path ), "run" , "python" , "-c" , "print('y')" ],
402+ cwd = tmp_path ,
403+ env = env ,
404+ )
405+
406+ check_process (result , exit_code = 0 , stdout = "x\n " )
407+
408+
347409def test_run_without_cmd (tmp_path ):
348410 result = run_dotenv (["run" ], cwd = tmp_path )
349411
0 commit comments