Completed
Push — master ( 4d55e8...9e8559 )
by Ionel Cristian
01:05
created

src.hunter.Tracer.handler()   A

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 3
rs 10
cc 1
1
from __future__ import absolute_import
2
3
import sys
4
import threading
5
6
from .event import Event
7
8
9
class Tracer(object):
10
    """
11
    Trace object.
12
13
    """
14
15
    def __init__(self, threading_support=False):
16
        self._handler = None
17
        self._previous = None
18
        self._threading_previous = None
19
        self.threading_support = threading_support
20
21
    @property
22
    def handler(self):
23
        return self._handler
24
25
    @property
26
    def previous(self):
27
        return self._previous
28
29
    def __repr__(self):
30
        return '<hunter.tracer.Tracer at 0x%x: threading_support=%s, %s%s%s%s>' % (
31
            id(self),
32
            self.threading_support,
33
            '<stopped>' if self._handler is None else 'handler=',
34
            '' if self._handler is None else repr(self._handler),
35
            '' if self._previous is None else ', previous=',
36
            '' if self._previous is None else repr(self._previous),
37
        )
38
39
    def __call__(self, frame, kind, arg):
40
        """
41
        The settrace function.
42
43
        .. note::
44
45
            This always returns self (drills down) - as opposed to only drilling down when predicate(event) is True
46
            because it might match further inside.
47
        """
48
        if self._handler is not None:
49
            self._handler(Event(frame, kind, arg, self))
50
            return self
51
52
    def trace(self, predicate):
53
        self._handler = predicate
54
        if self.threading_support:
55
            self._threading_previous = getattr(threading, '_trace_hook', None)
56
            threading.settrace(self)
57
        self._previous = sys.gettrace()
58
        sys.settrace(self)
59
        return self
60
61
    def stop(self):
62
        if self._handler is not None:
63
            sys.settrace(self._previous)
64
            self._handler = self._previous = None
65
            if self.threading_support:
66
                threading.settrace(self._threading_previous)
67
                self._threading_previous = None
68
69
    def __enter__(self):
70
        return self
71
72
    def __exit__(self, exc_type, exc_val, exc_tb):
73
        self.stop()
74