From 3597261f24e2ecc9e663f51bf5699b40baa1b6f4 Mon Sep 17 00:00:00 2001 From: Frost Ming Date: Fri, 1 Sep 2023 08:35:48 +0800 Subject: [PATCH 1/2] fix: `pdm run` conflicts between local file and PATH Fixes #2221 Signed-off-by: Frost Ming --- news/2221.bugfix.md | 1 + src/pdm/cli/commands/run.py | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 news/2221.bugfix.md diff --git a/news/2221.bugfix.md b/news/2221.bugfix.md new file mode 100644 index 0000000000..184a8912fd --- /dev/null +++ b/news/2221.bugfix.md @@ -0,0 +1 @@ +`pdm run` should only find local file if the command starts with `./`. diff --git a/src/pdm/cli/commands/run.py b/src/pdm/cli/commands/run.py index cd53656eba..4e20f5c622 100644 --- a/src/pdm/cli/commands/run.py +++ b/src/pdm/cli/commands/run.py @@ -121,8 +121,11 @@ def get_task(self, script_name: str) -> Task | None: def expand_command(self, command: str) -> str: expanded_command = os.path.expanduser(os.path.expandvars(command)) - if os.path.exists(expanded_command): - return os.path.abspath(expanded_command) + if expanded_command.replace(os.sep, "/").startswith(("./", "../")): + abspath = os.path.abspath(expanded_command) + if not os.path.isfile(abspath): + raise PdmUsageError(f"Command [success]'{command}'[/] is not a valid executable.") + return abspath result = self.project.environment.which(command) if not result: raise PdmUsageError(f"Command [success]'{command}'[/] is not found in your PATH.") From 319a8f7826ef1dfc6551b5ea6e29fb060171b310 Mon Sep 17 00:00:00 2001 From: Frost Ming Date: Fri, 1 Sep 2023 08:52:52 +0800 Subject: [PATCH 2/2] add tests Signed-off-by: Frost Ming --- tests/cli/test_run.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/cli/test_run.py b/tests/cli/test_run.py index 1742d5652c..4ce9765a49 100644 --- a/tests/cli/test_run.py +++ b/tests/cli/test_run.py @@ -152,6 +152,13 @@ def test_run_script_with_relative_path(project, pdm, capfd): assert out.strip() == "Hello" +def test_run_non_existing_local_script(project, pdm): + with cd(project.root): + result = pdm(["run", "./test_script.sh"], obj=project) + assert result.exit_code != 0 + assert "not a valid executable" in result.stderr + + @pytest.mark.parametrize( "args,expected", (