Skip to content

Commit

Permalink
Merge pull request #7745 from asottile/exec_globals_type_problem
Browse files Browse the repository at this point in the history
Fix INTERNALERROR when accessing locals / globals with faulty `exec`
  • Loading branch information
nicoddemus committed Sep 12, 2020
2 parents ec58ae5 + 96a17b1 commit 634cde9
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 3 deletions.
1 change: 1 addition & 0 deletions changelog/7742.bugfix.rst
@@ -0,0 +1 @@
Fix INTERNALERROR when accessing locals / globals with faulty ``exec``.
16 changes: 13 additions & 3 deletions src/_pytest/_code/code.py
Expand Up @@ -246,10 +246,20 @@ def ishidden(self) -> bool:
Mostly for internal use.
"""
f = self.frame
tbh = f.f_locals.get(
"__tracebackhide__", f.f_globals.get("__tracebackhide__", False)
tbh = (
False
) # type: Union[bool, Callable[[Optional[ExceptionInfo[BaseException]]], bool]]
for maybe_ns_dct in (self.frame.f_locals, self.frame.f_globals):
# in normal cases, f_locals and f_globals are dictionaries
# however via `exec(...)` / `eval(...)` they can be other types
# (even incorrect types!).
# as such, we suppress all exceptions while accessing __tracebackhide__
try:
tbh = maybe_ns_dct["__tracebackhide__"]
except Exception:
pass
else:
break
if tbh and callable(tbh):
return tbh(None if self._excinfo is None else self._excinfo())
return tbh
Expand Down
13 changes: 13 additions & 0 deletions testing/code/test_excinfo.py
Expand Up @@ -1352,6 +1352,19 @@ def unreraise():
)
assert out == expected_out

def test_exec_type_error_filter(self, importasmod):
"""See #7742"""
mod = importasmod(
"""\
def f():
exec("a = 1", {}, [])
"""
)
with pytest.raises(TypeError) as excinfo:
mod.f()
# previously crashed with `AttributeError: list has no attribute get`
excinfo.traceback.filter()


@pytest.mark.parametrize("style", ["short", "long"])
@pytest.mark.parametrize("encoding", [None, "utf8", "utf16"])
Expand Down

0 comments on commit 634cde9

Please sign in to comment.