Skip to content

Commit d3c2b54

Browse files
committed
Fix pyfuse.install_package_as
1 parent b15a9ee commit d3c2b54

3 files changed

Lines changed: 58 additions & 3 deletions

File tree

pyfuse/graph/analyzer.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,27 @@ def get_module_assignments(func: Callable[..., object]) -> dict[str, str]:
121121
return assignments
122122

123123

124+
def _is_install_package_as_call(expr: ast.expr) -> bool:
125+
"""Match ``install_package_as`` or ``pyfuse.install_package_as``."""
126+
if isinstance(expr, ast.Name):
127+
return expr.id == "install_package_as"
128+
if isinstance(expr, ast.Attribute):
129+
return expr.attr == "install_package_as"
130+
return False
131+
132+
124133
def _parse_install_package_as(node: ast.With) -> str | None:
125-
"""Return the package name if *node* is ``with install_package_as(...)``."""
134+
"""Return the package name if *node* is ``with install_package_as(...)``.
135+
136+
Accepts both the bare form (``install_package_as("foo")``) and the
137+
attribute form (``pyfuse.install_package_as("foo")``).
138+
"""
126139
if len(node.items) != 1:
127140
return None
128141
ctx = node.items[0].context_expr
129142
if not (
130143
isinstance(ctx, ast.Call)
131-
and isinstance(ctx.func, ast.Name)
132-
and ctx.func.id == "install_package_as"
144+
and _is_install_package_as_call(ctx.func)
133145
and len(ctx.args) == 1
134146
and isinstance(ctx.args[0], ast.Constant)
135147
and isinstance(ctx.args[0].value, str)

tests/test_deps.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import ast
2+
13
import pytest
24

35
from pyfuse.worker.deps import (
@@ -9,6 +11,7 @@
911
install_package_as,
1012
is_installed,
1113
)
14+
from pyfuse.graph.analyzer import _parse_install_package_as
1215
from pyfuse.core.models import FunctionNode, ImportInfo
1316
from pyfuse.graph.store import Store
1417

@@ -156,6 +159,32 @@ def test_package_none_from_dict_without_key(self) -> None:
156159
assert restored.package is None
157160

158161

162+
# -- _parse_install_package_as ----------------------------------------------
163+
164+
class TestParseInstallPackageAs:
165+
def _parse(self, source: str) -> str | None:
166+
tree = ast.parse(source)
167+
with_node = tree.body[0]
168+
assert isinstance(with_node, ast.With)
169+
return _parse_install_package_as(with_node)
170+
171+
def test_bare_form(self) -> None:
172+
assert self._parse('with install_package_as("PyYAML"):\n pass\n') == "PyYAML"
173+
174+
def test_attribute_form(self) -> None:
175+
"""``with pyfuse.install_package_as(...)`` is also recognized."""
176+
assert (
177+
self._parse('with pyfuse.install_package_as("python-multipart"):\n pass\n')
178+
== "python-multipart"
179+
)
180+
181+
def test_unrelated_with_block(self) -> None:
182+
assert self._parse('with open("x") as f:\n pass\n') is None
183+
184+
def test_missing_argument(self) -> None:
185+
assert self._parse('with install_package_as():\n pass\n') is None
186+
187+
159188
# -- _collect_package_hints --------------------------------------------------
160189

161190
class TestCollectPackageHints:

tests/test_venv.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,20 @@ def test_install_package_as(self, tmp_path: pytest.TempPathFactory) -> None:
202202
assert "yaml" not in packages
203203
assert "dateutil" not in packages
204204

205+
def test_install_package_as_attribute_form(
206+
self, tmp_path: pytest.TempPathFactory,
207+
) -> None:
208+
"""``with pyfuse.install_package_as(...)`` is also recognized."""
209+
script = tmp_path / "test_ipa_attr.py" # type: ignore[operator]
210+
script.write_text(
211+
"import pyfuse\n"
212+
'with pyfuse.install_package_as("python-multipart"):\n'
213+
" import multipart\n"
214+
)
215+
packages = _detect_script_packages(str(script))
216+
assert "python-multipart" in packages
217+
assert "multipart" not in packages
218+
205219

206220
class TestDetectPyfuseExtras:
207221
def test_connect_redis(self, tmp_path: pytest.TempPathFactory) -> None:

0 commit comments

Comments
 (0)