Repository: python-poetry/poetry

Issue:
Poetry run no longer executes local bash scripts
<!--
    Hi there! Thank you for submitting a bug report!

    Before you submit your issue, please review and follow the instructions at
    https://python-poetry.org/docs/contributing/#reporting-bugs. Fully fill out the template below; insufficient
    information or bad reproduction instructions will impair the ability of others to help you.
-->

<!-- All the below information must be provided for others to understand and help with your issue. -->
- **Poetry version**: 1.5.0
- **Python version**: 3.11.3
- **OS version and name**:  macOS 13.2.1 (22D68)
- **pyproject.toml**: [Basic pyproject.toml as created by `poetry new poetry-bug`](https://gist.github.com/oefe/1c8f02fa54de74b7f68807d024e5035d)

<!-- All the below steps should be completed before submitting your issue. Checked checkbox should look like this: [x] -->
- [x] I am on the [latest](https://github.com/python-poetry/poetry/releases/latest) stable Poetry version, installed using a recommended method.
- [x] I have searched the [issues](https://github.com/python-poetry/poetry/issues) of this repo and believe that this is not a duplicate.
- [x] I have consulted the [FAQ](https://python-poetry.org/docs/faq/) and [blog](https://python-poetry.org/blog/) for any relevant entries or release notes.
- [x] If an exception occurs when executing a command, I executed it again in debug mode (`-vvv` option) and have included the output below.

## Issue

In Poetry 1.4.2, you could execute local shell scripts using `poetry run`, e.g. `poetry run ./pyright.sh`.

This no longer works with Poetry 1.5

```
>ls -l *.sh
-rwxr-xr-x  1 user  staff  1871 May 19 17:49 pyright.sh*

>head -n 1 pyright.sh
#!/bin/bash

>poetry ./pyright.sh
The command "./pyright.sh" does not exist.

>poetry pyright.sh
The command "./pyright.sh" does not exist.
```

The changelog mentions #7606, but this should only affect python scripts listed in `[tool.poetry.scripts]`, which is not the case here.

So I would expect that this still works.

## Workaround

Explicitly calling `bash` with the script as argument, i.e. `poetry run bash ./pyright.sh` still works


Discussion:
Having the same issue for django projects here. They usually have a `manage.py` executable and in my case, I have a lot of scripts that does `poetry run ./manage.py ...` which are now failing

Resolving patch:
diff --git a/src/poetry/utils/env.py b/src/poetry/utils/env.py
--- a/src/poetry/utils/env.py
+++ b/src/poetry/utils/env.py
@@ -1243,7 +1243,7 @@ def python(self) -> Path:
         """
         Path to current python executable
         """
-        return self._bin(self._executable)
+        return Path(self._bin(self._executable))
 
     @property
     def marker_env(self) -> dict[str, Any]:
@@ -1311,7 +1311,7 @@ def pip(self) -> Path:
         """
         # we do not use as_posix() here due to issues with windows pathlib2
         # implementation
-        path = self._bin(self._pip_executable)
+        path = Path(self._bin(self._pip_executable))
         if not path.exists():
             return self.pip_embedded
         return path
@@ -1431,7 +1431,7 @@ def get_marker_env(self) -> dict[str, Any]:
         raise NotImplementedError()
 
     def get_pip_command(self, embedded: bool = False) -> list[str]:
-        if embedded or not self._bin(self._pip_executable).exists():
+        if embedded or not Path(self._bin(self._pip_executable)).exists():
             return [str(self.python), str(self.pip_embedded)]
         # run as module so that pip can update itself on Windows
         return [str(self.python), "-m", "pip"]
@@ -1461,7 +1461,7 @@ def get_command_from_bin(self, bin: str) -> list[str]:
             # embedded pip when pip is not available in the environment
             return self.get_pip_command()
 
-        return [str(self._bin(bin))]
+        return [self._bin(bin)]
 
     def run(self, bin: str, *args: str, **kwargs: Any) -> str:
         cmd = self.get_command_from_bin(bin) + list(args)
@@ -1541,7 +1541,7 @@ def script_dirs(self) -> list[Path]:
                 self._script_dirs.append(self.userbase / self._script_dirs[0].name)
         return self._script_dirs
 
-    def _bin(self, bin: str) -> Path:
+    def _bin(self, bin: str) -> str:
         """
         Return path to the given executable.
         """
@@ -1562,11 +1562,11 @@ def _bin(self, bin: str) -> Path:
                     bin_path = self._path / bin
 
                 if bin_path.exists():
-                    return bin_path
+                    return str(bin_path)
 
-            return Path(bin)
+            return bin
 
-        return bin_path
+        return str(bin_path)
 
     def __eq__(self, other: object) -> bool:
         if not isinstance(other, Env):
@@ -1880,8 +1880,8 @@ def execute(self, bin: str, *args: str, **kwargs: Any) -> int:
             return super().execute(bin, *args, **kwargs)
         return 0
 
-    def _bin(self, bin: str) -> Path:
-        return Path(bin)
+    def _bin(self, bin: str) -> str:
+        return bin
 
 
 @contextmanager


Test patch:
diff --git a/tests/utils/test_env.py b/tests/utils/test_env.py
--- a/tests/utils/test_env.py
+++ b/tests/utils/test_env.py
@@ -1827,3 +1827,10 @@ def test_detect_active_python_with_bat(poetry: Poetry, tmp_path: Path) -> None:
     active_python = EnvManager(poetry)._detect_active_python()
 
     assert active_python == wrapped_python
+
+
+def test_command_from_bin_preserves_relative_path(manager: EnvManager) -> None:
+    # https://github.com/python-poetry/poetry/issues/7959
+    env = manager.get()
+    command = env.get_command_from_bin("./foo.py")
+    assert command == ["./foo.py"]