Skip to content

Commit

Permalink
- fixed various cases get_info was causing errors while running on Fl…
Browse files Browse the repository at this point in the history
…ask;
  • Loading branch information
jaltmayerpizzorno committed Aug 28, 2024
1 parent 8918039 commit 07adcf6
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 4 deletions.
12 changes: 8 additions & 4 deletions src/coverup/codeinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def _resolve_from_import(file: Path, imp: ast.ImportFrom) -> str:

def _load_module(module_name: str) -> ast.Module | None:
try:
if (spec := importlib.util.find_spec(module_name)) and spec.origin:
if (spec := importlib.util.find_spec(module_name)) and spec.origin and spec.origin != 'frozen':
return parse_file(Path(spec.origin))

except ModuleNotFoundError:
Expand All @@ -68,7 +68,7 @@ def _auto_stack(func):
"""Decorator that adds a stack of the first argument of the function being called."""
def helper(*args):
helper.stack.append(args[0])
_debug(f"{'.'.join(getattr(n, 'name', '?') for n in helper.stack)}")
_debug(f"{'.'.join((n.name if getattr(n, 'name', None) else '?') for n in helper.stack)}")
retval = func(*args)
helper.stack.pop()
return retval
Expand Down Expand Up @@ -124,6 +124,7 @@ def _find_name_path(module: ast.Module, name: T.List[str], *, paths_seen: T.Set[
crossed to find it.
"""
if not module: return None
if not name: return None # TODO return module?

_debug(f"looking up {name} in {module.path}")

Expand All @@ -146,12 +147,13 @@ def find_name(node: ast.AST, name: T.List[str]) -> T.List[ast.AST]:
return [node, *path]

for base in node.bases:
base_name = ast.unparse(base).split('.')
if (len(find_name.stack) > 1 and
isinstance(context := find_name.stack[-2], ast.ClassDef)):
if (base_path := find_name(context, [context.name, base.id, *name[1:]])):
if (base_path := find_name(context, [context.name, *base_name, *name[1:]])):
return base_path[1:]

if (path := find_name(module, [base.id, *name[1:]])):
if (path := find_name(module, [*base_name, *name[1:]])):
return path

elif isinstance(module, (ast.Function, ast.AsyncFunction)):
Expand All @@ -171,6 +173,8 @@ def find_name(node: ast.AST, name: T.List[str]) -> T.List[ast.AST]:
if (path := _handle_import(module, node, name, paths_seen=paths_seen)):
return path

return []

elif not isinstance(node, (ast.Expression, ast.Expr, ast.Name)):
for c in ast.iter_child_nodes(node):
if (path := find_name(c, name)):
Expand Down
58 changes: 58 additions & 0 deletions tests/test_codeinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,36 @@ def a(self):
)


def test_get_info_method_from_parent_is_attribute(import_fixture):
tmp_path = import_fixture

code = tmp_path / "foo.py"
code.write_text(textwrap.dedent("""\
class A:
class B:
def a(self):
return 42
class C(A.B):
pass
"""
))

tree = codeinfo.parse_file(code)
assert codeinfo.get_info(tree, 'C.a') == textwrap.dedent("""\
```python
class A:
...
class B:
...
def a(self):
return 42
```"""
)


def test_get_info_method_from_parent_parent_missing(import_fixture):
tmp_path = import_fixture

Expand Down Expand Up @@ -1020,3 +1050,31 @@ def find_node(tree, name):
]


def test_get_info_module(import_fixture):
tmp_path = import_fixture

code = tmp_path / "foo.py"
code.write_text(textwrap.dedent("""\
import bar
"""
))
(tmp_path / "bar.py").write_text(textwrap.dedent("""\
answer = 42
"""
))

tree = codeinfo.parse_file(code)
assert codeinfo.get_info(tree, 'bar') == None


def test_get_info_frozen_module(import_fixture):
tmp_path = import_fixture

code = tmp_path / "foo.py"
code.write_text(textwrap.dedent("""\
import os
"""
))

tree = codeinfo.parse_file(code)
assert codeinfo.get_info(tree, 'os.path.join') == None

0 comments on commit 07adcf6

Please sign in to comment.