ionelmc / python-hunter

Hunter is a flexible code tracing toolkit.
https://python-hunter.readthedocs.io/
BSD 2-Clause "Simplified" License
796 stars 46 forks source link

Hunter doesn't work when using py.io #62

Closed chrahunt closed 5 years ago

chrahunt commented 5 years ago

When referencing py.io.TerminalWriter (probably other attributes as well), an exception is raised only when hunter is in use. Example:

import py.io

py.io.TerminalWriter
test -d .venv || python3 -m venv .venv
. .venv/bin/activate
pip install py==1.8.0 hunter==2.2.1
echo '
import py.io

py.io.TerminalWriter
' > test.py
python test.py

No exception should appear.

When running with hunter, like

PYTHONHUNTER='stdlib=False, action=CallPrinter(stream=open("hunter.log", "w", encoding="utf-8"))' python test.py

the following exception occurs:

Traceback (most recent call last):
  File ".venv/lib/python3.7/site-packages/py/_vendored_packages/apipkg.py", line 141, in __makeattr
    modpath, attrname = self.__map__[name]
KeyError: 'TerminalWriter'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test.py", line 4, in <module>
    py.io.TerminalWriter
  File ".venv/lib/python3.7/site-packages/py/_vendored_packages/apipkg.py", line 146, in __makeattr
    raise AttributeError(name)
AttributeError: TerminalWriter

The exception does not occur if we omit stdlib=False.

The exception does not occur when excluding the py._vendored_packages.apipkg, like:

PYTHONHUNTER='Q(stdlib=False) & ~Q(module="py._vendored_packages.apipkg"), action=CallPrinter(stream=open("hunter.log", "w", encoding="utf-8"))' python test.py

Doing some debugging around the area in apipkg it looks like the act of introspecting happens at a time that causes the exception to be raised. Maybe the method is not re-entrant, but the printing would require it to be?

In case there's a fundamental issue that can't be solved, adding documentation to call this out as a limitation would be good.

Additionally, we could use some documentation on what to watch out for when debugging hunter-related issues. Even basic debugging (e.g. breakpoint(), pdb, intentionally raising exceptions, logging) gives confusing feedback - messages logged at the top of __makeattr are printed twice but unconditional exceptions only visibly raised once, same with breakpoints.

ionelmc commented 5 years ago

Oooooof .... apipkg does some shenanigans with __dict__ of modules ... hunter.util.rudimentary_repr does a hasattr(obj, '__dict__') check 😞

ionelmc commented 5 years ago

A check like '__dict__' not in getattr(obj_type, '__dict__', ()) and not hasattr(obj, '__dict__') would fix it but then that would fail too if obj_type had a god damn descriptor as __dict__ ...

ionelmc commented 5 years ago

So there's a fix in master, give it a try.

chrahunt commented 5 years ago

Looks good to me!

ionelmc commented 5 years ago

Hunter 3.0 is released.