Package: hunter
Hunter is a flexible code tracing toolkit, not for measuring coverage, but for debugging, logging, inspection and other
nefarious purposes. It has asimple Python API,
aconvenient terminal APIand
aCLI tool to attach to processes.Free software: BSD 2-Clause LicenseInstallationpip install hunterDocumentationhttps://python-hunter.readthedocs.io/Getting startedBasic use involves passing various filters to thetraceoption. An example:importhunterhunter.trace(module='posixpath',action=hunter.CallPrinter)importosos.path.join('a','b')That would result in:>>>os.path.join('a','b')/usr/lib/python3.6/posixpath.py:75    call      => join(a='a')
         /usr/lib/python3.6/posixpath.py:80    line         a = os.fspath(a)
         /usr/lib/python3.6/posixpath.py:81    line         sep = _get_sep(a)
         /usr/lib/python3.6/posixpath.py:41    call         => _get_sep(path='a')
         /usr/lib/python3.6/posixpath.py:42    line            if isinstance(path, bytes):
         /usr/lib/python3.6/posixpath.py:45    line            return '/'
         /usr/lib/python3.6/posixpath.py:45    return       <= _get_sep: '/'
         /usr/lib/python3.6/posixpath.py:82    line         path = a
         /usr/lib/python3.6/posixpath.py:83    line         try:
         /usr/lib/python3.6/posixpath.py:84    line         if not p:
         /usr/lib/python3.6/posixpath.py:86    line         for b in map(os.fspath, p):
         /usr/lib/python3.6/posixpath.py:87    line         if b.startswith(sep):
         /usr/lib/python3.6/posixpath.py:89    line         elif not path or path.endswith(sep):
         /usr/lib/python3.6/posixpath.py:92    line         path += sep + b
         /usr/lib/python3.6/posixpath.py:86    line         for b in map(os.fspath, p):
         /usr/lib/python3.6/posixpath.py:96    line         return path
         /usr/lib/python3.6/posixpath.py:96    return    <= join: 'a/b'
'a/b'In a terminal it would look like:Another useful scenario is to ignore all standard modules and force colors to make them stay even if the output is
redirected to a file.importhunterhunter.trace(stdlib=False,action=hunter.CallPrinter(force_colors=True))ActionsOutput format can be controlled with “actions”. There’s an alternativeCodePrinteraction that doesn’t handle
nesting (it was the default action until Hunter 2.0).If filters match then action will be run. Example:importhunterhunter.trace(module='posixpath',action=hunter.CodePrinter)importosos.path.join('a','b')That would result in:>>>os.path.join('a','b')/usr/lib/python3.6/posixpath.py:75    call      def join(a, *p):
         /usr/lib/python3.6/posixpath.py:80    line          a = os.fspath(a)
         /usr/lib/python3.6/posixpath.py:81    line          sep = _get_sep(a)
         /usr/lib/python3.6/posixpath.py:41    call      def _get_sep(path):
         /usr/lib/python3.6/posixpath.py:42    line          if isinstance(path, bytes):
         /usr/lib/python3.6/posixpath.py:45    line              return '/'
         /usr/lib/python3.6/posixpath.py:45    return            return '/'
                                               ...       return value: '/'
         /usr/lib/python3.6/posixpath.py:82    line          path = a
         /usr/lib/python3.6/posixpath.py:83    line          try:
         /usr/lib/python3.6/posixpath.py:84    line              if not p:
         /usr/lib/python3.6/posixpath.py:86    line              for b in map(os.fspath, p):
         /usr/lib/python3.6/posixpath.py:87    line                  if b.startswith(sep):
         /usr/lib/python3.6/posixpath.py:89    line                  elif not path or path.endswith(sep):
         /usr/lib/python3.6/posixpath.py:92    line                      path += sep + b
         /usr/lib/python3.6/posixpath.py:86    line              for b in map(os.fspath, p):
         /usr/lib/python3.6/posixpath.py:96    line          return path
         /usr/lib/python3.6/posixpath.py:96    return        return path
                                               ...       return value: 'a/b'
'a/b'or in a terminal:Another useful action is theVarsPrinter:importhunter# note that this kind of invocation will also use the default `CallPrinter` actionhunter.trace(hunter.Q(module='posixpath',action=hunter.VarsPrinter('path')))importosos.path.join('a','b')That would result in:>>>os.path.join('a','b')/usr/lib/python3.6/posixpath.py:75    call      => join(a='a')
     /usr/lib/python3.6/posixpath.py:80    line         a = os.fspath(a)
     /usr/lib/python3.6/posixpath.py:81    line         sep = _get_sep(a)
     /usr/lib/python3.6/posixpath.py:41    call      [path => 'a']
     /usr/lib/python3.6/posixpath.py:41    call         => _get_sep(path='a')
     /usr/lib/python3.6/posixpath.py:42    line      [path => 'a']
     /usr/lib/python3.6/posixpath.py:42    line            if isinstance(path, bytes):
     /usr/lib/python3.6/posixpath.py:45    line      [path => 'a']
     /usr/lib/python3.6/posixpath.py:45    line            return '/'
     /usr/lib/python3.6/posixpath.py:45    return    [path => 'a']
     /usr/lib/python3.6/posixpath.py:45    return       <= _get_sep: '/'
     /usr/lib/python3.6/posixpath.py:82    line         path = a
     /usr/lib/python3.6/posixpath.py:83    line      [path => 'a']
     /usr/lib/python3.6/posixpath.py:83    line         try:
     /usr/lib/python3.6/posixpath.py:84    line      [path => 'a']
     /usr/lib/python3.6/posixpath.py:84    line         if not p:
     /usr/lib/python3.6/posixpath.py:86    line      [path => 'a']
     /usr/lib/python3.6/posixpath.py:86    line         for b in map(os.fspath, p):
     /usr/lib/python3.6/posixpath.py:87    line      [path => 'a']
     /usr/lib/python3.6/posixpath.py:87    line         if b.startswith(sep):
     /usr/lib/python3.6/posixpath.py:89    line      [path => 'a']
     /usr/lib/python3.6/posixpath.py:89    line         elif not path or path.endswith(sep):
     /usr/lib/python3.6/posixpath.py:92    line      [path => 'a']
     /usr/lib/python3.6/posixpath.py:92    line         path += sep + b
     /usr/lib/python3.6/posixpath.py:86    line      [path => 'a/b']
     /usr/lib/python3.6/posixpath.py:86    line         for b in map(os.fspath, p):
     /usr/lib/python3.6/posixpath.py:96    line      [path => 'a/b']
     /usr/lib/python3.6/posixpath.py:96    line         return path
     /usr/lib/python3.6/posixpath.py:96    return    [path => 'a/b']
     /usr/lib/python3.6/posixpath.py:96    return    <= join: 'a/b'
'a/b'In a terminal it would look like:You can give it a tree-like configuration where you can optionally configure specific actions for parts of the
tree (like dumping variables or a pdb set_trace):fromhunterimporttrace,Q,DebuggerfrompdbimportPdbtrace(# drop into a Pdb session if ``foo.bar()`` is calledQ(module="foo",function="bar",kind="call",action=Debugger(klass=Pdb))|# orQ(# show code that contains "mumbo.jumbo" on the current linelambdaevent:event.locals.get("mumbo")=="jumbo",# and it's not in Python's stdlibstdlib=False,# and it contains "mumbo" on the current linesource__contains="mumbo"))importfoofoo.func()With afoo.pylike this:defbar():execution_will_get_stopped# cause we get a Pdb session heredeffunc():mumbo=1mumbo="jumbo"print("not shown in trace")print(mumbo)mumbo=2print(mumbo)# not shown in tracebar()We get:>>>foo.func()not shown in trace
    /home/ionel/osp/python-hunter/foo.py:8     line          print(mumbo)
jumbo
    /home/ionel/osp/python-hunter/foo.py:9     line          mumbo = 2
2
    /home/ionel/osp/python-hunter/foo.py:1     call      def bar():
> /home/ionel/osp/python-hunter/foo.py(2)bar()
-> execution_will_get_stopped  # cause we get a Pdb session here
(Pdb)In a terminal it would look like:Tracing processesIn similar fashion tostraceHunter can trace other processes, eg:hunter-trace --gdb -p 123If you wanna play it safe (no messy GDB) then add this in your code:from hunter import remote
remote.install()Then you can do:hunter-trace -p 123Seedocs on the remote feature.Note:Windows ain’t supported.Environment variable activationFor your convenience environment variable activation is available. Just run your app like this:PYTHONHUNTER="module='os.path'" python yourapp.pyOn Windows you’d do something like:set PYTHONHUNTER=module='os.path'
python yourapp.pyThe activation works with a clever.pthfile that checks for that env var presence and before your app runs does something
like this:from hunter import *
trace(<whatever-you-had-in-the-PYTHONHUNTER-env-var>)Note that Hunter is activated even if the env var is empty, eg:PYTHONHUNTER="".Environment variable configurationSometimes you always use the same options (likestdlib=Falseorforce_colors=True). To save typing you can
set something like this in your environment:PYTHONHUNTERCONFIG="stdlib=False,force_colors=True"This is the same asPYTHONHUNTER="stdlib=False,action=CallPrinter(force_colors=True)".Notes:SettingPYTHONHUNTERCONFIGalone doesn’t activate hunter.All the options for the builtin actions are supported.Although using predicates is supported it can be problematic. Example of setup that won’t trace anything:PYTHONHUNTERCONFIG="Q(module_startswith='django')"
PYTHONHUNTER="Q(module_startswith='celery')"which is the equivalent of:PYTHONHUNTER="Q(module_startswith='django'),Q(module_startswith='celery')"which is the equivalent of:PYTHONHUNTER="Q(module_startswith='django')&Q(module_startswith='celery')"Filtering DSLHunter supports a flexible query DSL, see theintroduction.DevelopmentTo run the all tests run:toxDesign notesHunter doesn’t do everything. As a design goal of this library some things are made intentionally austere and verbose (to avoid complexity,
confusion and inconsistency). This has few consequences:There areOperatorsbut there’s no negation operator.
Instead you’re expected to negate a Query object, eg:~Q(module='re').There are no specialized operators or filters - all filters behave exactly the same. For example:No filter for packages. You’re expected to filter by module with an operator.No filter for arguments, return values or variables. You’re expected to write your own filter function and deal with the problems
of poking into objects.Layering is minimal. There’s are somehelpersthat do
some argument processing and conversions to save you some typing but that’s about it.The library doesn’t try to hide the mechanics of tracing in Python - it’s 1:1 regarding what Python sends to a trace function if you’d be
usingsys.settrace.Doesn’t have any storage. You are expected to redirect output to a file.You should look at it like it’s a tool to help you understand and debug big applications, or a framework ridding you of the boring parts of
settrace, not something that helps you learn Python.FAQWhy not Smiley?There’s some obvious overlap withsmileybut there are few fundamental differences:Complexity. Smiley is simply over-engineered:It uses IPC and a SQL database.It has a webserver. Lots of dependencies.It uses threads. Side-effects and subtle bugs are introduced in your code.It records everything. Tries to dump any variable. Often fails and stops working.Why do you need all that just to debug some stuff in a terminal? Simply put, it’s a nice idea but the design choices work
against you when you’re already neck-deep into debugging your own code. In my experience Smiley has been very buggy and
unreliable. Your mileage may vary of course.Tracing long running code. This will make Smiley record lots of data, making it unusable.Now because Smiley records everything, you’d think it’s better suited for short programs. But alas, if your program runs
quickly then it’s pointless to record the execution. You can just run it again.It seems there’s only one situation where it’s reasonable to use Smiley: tracing io-bound apps remotely. Those apps don’t
execute lots of code, they just wait on network so Smiley’s storage won’t blow out of proportion and tracing overhead might
be acceptable.Use-cases. It seems to me Smiley’s purpose is not really debugging code, but more of a “non interactive monitoring” tool.In contrast, Hunter is very simple:Few dependencies.Low overhead (tracing/filtering code has an optional Cython extension).No storage. This simplifies lots of things.The only cost is that you might need to run the code multiple times to get the filtering/actions right. This means Hunter is
not really suited for “post-mortem” debugging. If you can’t reproduce the problem anymore then Hunter won’t be of much help.Why not pytrace?Pytraceis another tracer tool. It seems quite similar to Smiley - it uses a sqlite
database for the events, threads and IPC, thus it’s reasonable to expect the same kind of problems.Why not PySnooper or snoop?snoopis a refined version ofPySnooper. Both are
more suited to tracing small programs or functions as the output is more verbose and less suited to the needs of tracing a big application
where Hunter provides more flexible setup, filtering capabilities, speed and brevity.Why not coverage?For purposes of debuggingcoverageis a great tool but only as far as “debugging
by looking at what code is (not) run”. Checking branch coverage is good but it will only get you as far.From the other perspective, you’d be wondering if you could use Hunter to measure coverage-like things. You could do it but
for that purpose Hunter is very “rough”: it has no builtin storage. You’d have to implement your own storage. You can do it
but it wouldn’t give you any advantage over making your own tracer if you don’t need to “pre-filter” whatever you’re
recording.In other words, filtering events is the main selling point of Hunter - it’s fast (cython implementation) and the query API is
flexible enough.Projects using HunterNoteworthy usages or Hunter (submit a PR with your project if you built a tool that relies on hunter):Crunch-io/diagnose- a runtime instrumentation library.talwrii/huntrace- an alternative cli (similar to ltrace).anki-code/xunter- a profiling tool made specifically forthe xonsh shell.More projects using it athttps://github.com/ionelmc/python-hunter/network/dependentsChangelog3.6.1 (2023-04-26)Added safe repr support for Decimal objects.3.6.0 (2023-04-25)Added C extension support for Python 3.11. This may come with up to 10% performance hit (depending on use-case) for all Pythons.
Unfortunately somecompat shimsare
now used for getting frame details. This is necessary to be able to work with Python 3.11 and be more future-proof.Added safe repr support for ZoneInfo objects.C extension files are now prebuilt with Cython 3.0b2.Replaced the flake8/isort pre-commit hooks with ruff.Disabled editable wheels (PEP-0662) as they don’t include thehunter.pthfile.
There may be a way to do it but I haven’t figured out a way to customize theeditable_wheelcommand without a
very brittle solution glued to setuptools’ internals.3.5.1 (2022-09-27)Fixed breakage inhunter-tracewhen Ctrl-C.3.5.0 (2022-09-11)Add support for generators and coroutines in thehunter.wrapdecorator.Dropped support for Python 3.6.3.4.3 (2021-12-15)Removed most of the Python 2 support code.Fix some refactoring regression insetup.pyand make the 3.4.x series installable only on Python 3.6 and later.Yank 3.4.0, 3.4.1, 3.4.2 releases to avoid install problems on Python 2.7.3.4.2 (2021-12-15)Fixed CI to properly make win32 wheels.3.4.1 (2021-12-14)Add support for building app37.pp38tagged wheel
(basically an universal wheel installable just for those two PyPy versions).3.4.0 (2021-12-14)Switched CI to GitHub Actions, this has a couple consequences:Support for Python 2.7 is dropped. You can still install it there but it’s not tested anymore and
Python 2 specific handling will be removed at some point.Linux wheels are now provided inmusllinuxandmanylinux2014variants.Extension building is now completely skipped on PyPy.A pure but tagged as platform specific wheel is now provided for PyPy (to have fast installs there as well).3.3.8 (2021-06-23)Fixed CI problem that publishes same type of wheels two times.3.3.7 (2021-06-23)Fixed a bug with howstdlibis detected on Windows (at least).3.3.6 (2021-06-23)Fixed regression from3.3.4:stdlibfilter was broken.Improved the pth file (PYTHONHUNTERenvironment variable activation) to use a clean eval environment.
No bogus variables likeline(from thesite.pymachinery) will be available anymore.Fixed a bug inVarsSnooperthat would make it fail in rare situation where a doublereturnevent is emitted.3.3.5 (2021-06-11)Added support for Python 3.10.Added support fortimeobjects and thefoldoption insafe_repr.3.3.4 was skipped cause I messed up the CI.3.3.3 (2021-05-04)Fixed tracer still being active for other threads after it was stopped.Python unfortunately only allows removing the trace function for the current thread -
nowhunter.tracer.Tracerwill uninstall itself if it’s marked as stopped.This fixes bogus errors that appear when usingipdbwith
thehunter.actions.Debuggeraction while thread support is enabled (the default).3.3.2 (2021-03-25)Changed CI to build Python 3.9 wheels. Python 3.5 no longer tested and wheels no longer built to keep things simple.Documentation improvements.3.3.1 (2020-10-24)Fixed CI/test issues that prevented all of 21 wheels being published.3.3.0 (2020-10-23)Fixed handling so thathunter.event.Event.moduleis always the"?"string instead ofNone.
Previously it wasNonewhen tracing particularly broken code and broke various predicates.Similarlyhunter.event.Event.filenameis now"?"if there’s no filename available.Building on the previous changes the actions have simpler code for displaying missing module/filenames.Changedhunter.actions.CallPrinterso that trace events for builtin functions are displayed differently.
These events appear when using profile mode (eg:trace(profile=True)).Fixed failure that could occur ifhunter.event.Event.moduleis an unicode string. Now it’s always a regular string.Only applies to Python 2.Fixed argument display when tracing functions with tuple arguments.
Closes#88.Only applies to Python 2.Improved error reporting when internal failures occur. Now some details about the triggering event are logged.3.2.2 (2020-09-04)Fixed oversight over what value is inhunter.event.Event.builtin. Now it’s always a boolean, and can be used consistently
in filters (eg:builtin=True,function='getattr').3.2.1 (2020-08-18)Added support for regex, date and datetime insafe_repr.Fixed call argument display when positional and keyword arguments are used inhunter.actions.CallPrinter.3.2.0 (2020-08-16)Implemented thehunter.actions.StackPrinteraction.Implemented thehunter.predicates.Backlogpredicate.
Contributed by Dan Ailenei in#81.Improved contributing section in docs a bit.
Contributed by Tom Schraitle in#85.Improved filtering performance by avoiding a lot of unnecessaryPyObject_GetAttrcalls in the Cython implementation ofhunter.predicates.Backlog.Implemented thehunter.actions.ErrorSnooperaction.Added support for profiling mode (eg:trace(profile=True)).
This mode will usesetprofileinstead ofsettrace.Added ARM64 wheels and CI.Addedhunter.event.Event.instructionandhunter.event.Event.builtin(usable in profile mode).Added more cookbook entries.3.1.3 (2020-02-02)Improved again the stdlib check to handle certain paths better.3.1.2 (2019-01-19)Really fixed the<frozen importlib.somethingstdlib check.3.1.1 (2019-01-19)Marked all the<frozen importlib.somethingfiles as part of stdlib.3.1.0 (2019-01-19)Addedhunter.actions.ErrorSnooper- an action that detects silenced exceptions.Addedhunter.load_configand fixed issues with configuration being loaded too late from thePYTHONHUNTERCONFIGenvironment
variable.Changedhunter.Fromhelper to automatically movedepthandcallsfilters to the predicate (so they filter afterhunter.predicates.Fromactivates).Changedhunter.predicates.Fromto pass a copy of event to the predicate.
The copy will have thedepthandcallsattributes adjusted to the point wherehunter.predicates.Fromactivated.Fixed a bunch of inconsistencies and bugs when using&and|operators with predicates.Fixed a bunch of broken fields ondetached events <hunter.event.Event.detach>(hunter.event.Event.function_objectandhunter.event.Event.arg).Improved docstrings in various and added a configuration doc section.Improved testing (more coverage).3.0.5 (2019-12-06)Really fixedsafe_reprso it doesn’t cause side-effects (now isinstance/issubclass are avoided - they
can cause side-effects in code that abuses descriptors in special attributes/methods).3.0.4 (2019-10-26)Really fixedstreamsetup in actions (usingforce_colorswithout anystreamwas broken).
See:hunter.actions.ColorStreamAction.Fixed__repr__for thehunter.predicates.Frompredicate to includewatermark.Added binary wheels for Python 3.8.3.0.3 (2019-10-13)Fixedsafe_repron pypy so it’s safer on method objects.
See:hunter.actions.ColorStreamAction.3.0.2 (2019-10-10)Fixed settingstreamfromPYTHONHUNTERCONFIGenvironment variable.
See:hunter.actions.ColorStreamAction.Fixed a couple minor documentation issues.3.0.1 (2019-06-17)Fixed issue with coloring missing source message (coloring leaked into next line).3.0.0 (2019-06-17)The package now uses setuptools-scm for development builds (available athttps://test.pypi.org/project/hunter/). As a
consequence installing the sdist will download setuptools-scm.Recompiled cython modules with latest Cython. Hunter can be installed without any Cython, as before.Refactored some of the cython modules to have more typing information and not use deprecated property syntax.Replacedunsafe_reproption withrepr_func. Now you can use your custom repr function in the builtin actions.BACKWARDS INCOMPATIBLEFixed buggy filename handling when using Hunter in ipython/jupyter. Source code should be properly displayed now.Removedglobalsoption fromVarsPrinteraction. Globals are now always looked up.BACKWARDS INCOMPATIBLEAdded support for locals inVarsPrinteraction. Now you can doVarsPrinter('len(foobar)').Always pass module_globals dict to linecache methods. Source code from PEP-302 loaders is now printed properly.
Contributed by Mikhail Borisov in#65.Various code cleanup, style and docstring fixing.Addedhunter.Fromhelper to allow passing in filters directly as keyword arguments.Addedhunter.event.Event.detachfor storing events without leaks or side-effects (due to prolonged references
to Frame objects, local or global variables).Refactored the internals of actions for easier subclassing.Added thehunter.actions.ColorStreamAction.filename_prefix,hunter.actions.ColorStreamAction.output,hunter.actions.ColorStreamAction.pid_prefix,hunter.actions.ColorStreamAction.thread_prefix,hunter.actions.ColorStreamAction.try_reprandhunter.actions.ColorStreamAction.try_sourcemethods
to thehunter.actions.ColorStreamActionbaseclass.Addedhunter.actions.VarsSnooper- a PySnooper-inspired variant ofhunter.actions.VarsPrinter. It
will record and show variable changes, with the risk of leaking or using too much memory of course :)Fixed tracers to log error and automatically stop if there’s an internal failure. Previously error may have been
silently dropped in some situations.2.2.1 (2019-01-19)Fixed a link in changelog.Fixed some issues in the Travis configuration.2.2.0 (2019-01-19)Addedhunter.predicates.Frompredicate for tracing from a specific point. It stop after returning back to the
same call depth with a configurable offset.FixedPYTHONHUNTERCONFIGnot working in some situations (config values were resolved at the wrong time).Made tests in CI test the wheel that will eventually be published to PyPI
(tox-wheel).Madeevent.stdlibmore reliable:pkg_resourcesis considered part of stdlib and few more paths will be
considered as stdlib.Dumbed down theget_peercredcheck that is done when attaching withhunter-traceCLI (viahunter.remote.install()). It will be slightly insecure but will work on OSX.Added OSX in the Travis test grid.2.1.0 (2018-11-17)Madethreading_supporton by default but output automatic (also, now1or0allowed).Addedpid_alignmentandforce_pidaction options to show a pid prefix.Fixed some bugs around__eq__in various classes.Dropped Python 3.3 support.Dropped dependency onfields.Actions now repr using a simplified implementation that tries to avoid calling__repr__on user classes in order
to avoid creating side-effects while tracing.Added support for thePYTHONHUNTERCONFIGenvironment variable (stores defaults and doesn’t activate hunter).2.0.2 (2017-11-24)Fixed indentation inhunter.actions.CallPrinteraction (shouldn’t deindent on exception).Fixed option filtering in Cython Query implementation (filtering ontracerwas allowed by mistake).Various fixes to docstrings and docs.2.0.1 (2017-09-09)NowPy_AddPendingCallis used instead of acquiring the GIL (when using GDB).2.0.0 (2017-09-02)Added thehunter.event.Event.countandhunter.event.Event.callsattributes.Added thelt/lte/gt/gtelookups.Added convenience aliases forstartswith(sw),endswith(ew),contains(has)
andregex(rx).Added a conveniencehunter.wrapdecorator to start tracing around a function.Added support for remote tracing (with two backends:manholeand GDB) via
thehunter-tracebin. Note:Windows is NOT SUPPORTED.Changed the default action tohunter.actions.CallPrinter.
You’ll need to useaction=CodePrinterif you want the old output.1.4.1 (2016-09-24)Fix support for getting sources for Cython module (it was broken on Windows and Python3.5+).1.4.0 (2016-09-24)Added support for tracing Cython modules (#30). A# cython: linetrace=Truestanza or equivalent is required in Cython modules for this to work.1.3.0 (2016-04-14)Addedhunter.event.Event.thread.Addedhunter.event.Event.threadidandhunter.event.Event.threadname(available for filtering withhunter.Q).Addedhunter.event.Event.threading_supportargument tohunter.trace.
It makes new threads be traced and changes action output to include thread name.Added support for usingpdb++in thehunter.actions.Debuggeraction.Added support for usingmanholevia a newhunter.actions.Manholeaction.Made thehunter.event.Event.handlera public but readonly property.1.2.2 (2016-01-28)Fix broken import. Requirefields>=4.0.Simplify a string check in Cython code.1.2.1 (2016-01-27)Fix “KeyError: ‘normal’” bug inhunter.actions.CallPrinter. Create the NO_COLORS dict from the COLOR dicts.
Some keys were missing.1.2.0 (2016-01-24)Fixed printouts of objects that return very large string in__repr__(). Trimmed to 512. Configurable in actions
with therepr_limitoption.Improved validation ofhunter.actions.VarsPrinter’s initializer.Added ahunter.actions.CallPrinteraction.1.1.0 (2016-01-21)Implemented a destructor (__dealloc__) for the Cython tracer.Improved the restoring of the previous tracer in the Cython tracer (usePyEval_SetTrace) directly.Removedtraceras an allowed filtering argument inhunter.Query.Add basic validation (must be callable) for positional arguments and actions passed intohunter.Q. Closes#23.Fixedstdlibchecks (wasn’t very reliable). Closes#24.1.0.2 (2016-01-05)Fixed missing import insetup.py.1.0.1 (2015-12-24)Fix a compile issue with the MSVC compiler (seems it don’t like the inline option on thefast_When_call).1.0.0 (2015-12-24)Implemented fast tracer and query objects in Cython.MAY BE BACKWARDS INCOMPATIBLETo force using the old pure-python implementation set thePUREPYTHONHUNTERenvironment variable to non-empty value.Added filtering operators:contains,startswith,endswithandin. Examples:Q(module_startswith='foo'will match events fromfoo,foo.barandfoobar.Q(module_startswith=['foo','bar']will match events fromfoo,foo.bar,foobar,bar,bar.fooandbaroo.Q(module_endswith='bar'will match events fromfoo.barandfoobar.Q(module_contains='ip'will match events fromlipsum.Q(module_in=['foo','bar']will match events fromfooandbar.Q(module_regex=r"(re|sre.*)\b")will match events from ``re,re.foobar,srefoobarbut not fromrepr.Removed themergeoption. Now when you callhunter.trace(...)multiple times only the last one is active.BACKWARDS INCOMPATIBLERemove theprevious_tracerhandling. Now when you callhunter.trace(...)the previous tracer (whatever was insys.gettrace()) is disabled and restored whenhunter.stop()is called.BACKWARDS INCOMPATIBLEFixedCodePrinterto show module name if it fails to get any sources.0.6.0 (2015-10-10)Added aclear_env_varoption on the tracer (disables tracing in subprocess).Addedforce_colorsoption onhunter.actions.VarsPrinterandhunter.actions.CodePrinter.Allowed setting thestreamto a file name (option onhunter.actions.VarsPrinterandhunter.actions.CodePrinter).Bumped up the filename alignment to 40 cols.If not merging thenselfis not kept as a previous tracer anymore.
Closes#16.Fixed handling in VarsPrinter: properly print eval errors and don’t try to show anything if there’s an AttributeError.
Closes#18.Added astdlibboolean flag (for filtering purposes).
Closes#15.Fixed broken frames that have “None” for filename or module (so they can still be treated as strings).Corrected output files in theinstall_libcommand so that pip can uninstall the pth file.
This only works when it’s installed with pip (sadly,setup.py install/developandpip install-ewill still
leave pth garbage onpip uninstall hunter).0.5.1 (2015-04-15)Fixedhunter.event.Event.globalsto actually be the dict of global vars (it was just the locals).0.5.0 (2015-04-06)Fixedhunter.Andandhunter.Or“single argument unwrapping”.Implemented predicate compression. Example:Or(Or(a, b), c)is converted toOr(a, b, c).Renamedhunter.event.Event.sourcetohunter.event.Event.fullsource.Addedhunter.event.Event.sourcethat doesn’t do any fancy sourcecode tokenization.Fixedhunter.event.Event.fullsourcereturn value for situations where the tokenizer would fail.Made the print function available in thePYTHONHUNTERenv var payload.Added a __repr__ forhunter.event.Event.0.4.0 (2015-03-29)Disabled colors for Jython.
Contributed by Claudiu Popa in#12.Test suite fixes for Windows.
Contributed by Claudiu Popa in#11.Added an introduction section in the docs.Implemented a prettier fallback for when no sources are available for that frame.Implemented fixups in cases where you use action classes as a predicates.0.3.1 (2015-03-29)Forgot to merge some commits …0.3.0 (2015-03-29)Added handling for internal repr failures.Fixed issues with displaying code that has non-ascii characters.Implemented better display forcallframes so that when a function has decorators the
function definition is shown (instead of just the first decorator).
See:#8.0.2.1 (2015-03-28)Added missing color entry for exception events.Addedhunter.event.Event.lineproperty. It returns the source code for the line being run.0.2.0 (2015-03-27)Added color support (andcoloramaas dependency).Added support for expressions inhunter.actions.VarsPrinter.Breaking changes:RenamedFtohunter.Q. Andhunter.Qis now just a convenience wrapper forhunter.predicates.Query.Renamed thePYTHON_HUNTERenv variable toPYTHONHUNTER.Changedhunter.predicates.Whento take positional arguments.Changed output to show 2 path components (still not configurable).Changedhunter.actions.VarsPrinterto take positional arguments for the names.Improved error reporting for env variable activation (PYTHONHUNTER).Fixed env var activator (the.pthfile) installation withsetup.py install(the “egg installs”) andsetup.py develop/pip install-e(the “egg links”).0.1.0 (2015-03-22)First release on PyPI.