Skip to content

Commit 3dc570b

Browse files
chryslehuxuan
andauthored
Fix pipx run entry point discovery with local path (#1422)
* Fix `pipx run` entry point discovery with local path * Add news fragment --------- Co-authored-by: Xuan (Sean) Hu <[email protected]>
1 parent 959e2ff commit 3dc570b

File tree

4 files changed

+25
-3
lines changed

4 files changed

+25
-3
lines changed

changelog.d/1422.bugfix.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix discovery of a `pipx run` entry point if a local path was given as package.

src/pipx/venv.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -400,8 +400,13 @@ def _find_entry_point(self, app: str) -> Optional[EntryPoint]:
400400
dists = Distribution.discover(name=self.main_package_name, path=[str(get_site_packages(self.python_path))])
401401
for dist in dists:
402402
for ep in dist.entry_points:
403-
if ep.group == "pipx.run" and ep.name == app:
404-
return ep
403+
if ep.group == "pipx.run":
404+
if ep.name == app:
405+
return ep
406+
# Try to infer app name from dist's metadata if given
407+
# local path
408+
if Path(app).exists() and dist.metadata["Name"] == ep.name:
409+
return ep
405410
return None
406411

407412
def run_app(self, app: str, filename: str, app_args: List[str]) -> NoReturn:
@@ -416,6 +421,7 @@ def run_app(self, app: str, filename: str, app_args: List[str]) -> NoReturn:
416421
# "entry_point.module" and "entry_point.attr" instead.
417422
match = _entry_point_value_pattern.match(entry_point.value)
418423
assert match is not None, "invalid entry point"
424+
logger.info("Using discovered entry point for 'pipx run'")
419425
module, attr = match.group("module", "attr")
420426
code = f"import sys, {module}\nsys.argv[0] = {entry_point.name!r}\nsys.exit({module}.{attr}())\n"
421427
exec_app([str(self.python_path), "-c", code] + app_args)

testdata/empty_project/pyproject.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
[build-system]
2+
build-backend = "setuptools.build_meta"
3+
24
requires = [
35
"setuptools",
4-
"wheel",
56
]
67

78
[project]
@@ -21,3 +22,4 @@ classifiers = [
2122
"Programming Language :: Python :: 3.12",
2223
]
2324
scripts.empty-project = "empty_project.main:cli"
25+
entry-points."pipx.run".empty-project = "empty_project.main:cli"

tests/test_run.py

+13
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import subprocess
44
import sys
55
import textwrap
6+
from pathlib import Path
67
from unittest import mock
78

89
import pytest # type: ignore[import-not-found]
@@ -401,3 +402,15 @@ def test_run_shared_lib_as_app(pipx_temp_env, monkeypatch, capfd):
401402
run_pipx_cli_exit(["run", "pip", "--help"])
402403
captured = capfd.readouterr()
403404
assert "pip <command> [options]" in captured.out
405+
406+
407+
@mock.patch("os.execvpe", new=execvpe_mock)
408+
def test_run_local_path_entry_point(pipx_temp_env, caplog, root):
409+
empty_project_path = (Path("testdata") / "empty_project").as_posix()
410+
os.chdir(root)
411+
412+
caplog.set_level(logging.INFO)
413+
414+
run_pipx_cli_exit(["run", empty_project_path])
415+
416+
assert "Using discovered entry point for 'pipx run'" in caplog.text

0 commit comments

Comments
 (0)