Completed
Push — master ( 4e3b27...2dc96c )
by Ionel Cristian
56s
created

src.hunter.Not.__repr__()   A

Complexity

Conditions 1

Size

Total Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 2
rs 10
cc 1
1
from __future__ import absolute_import
2
3
import inspect
4
from itertools import chain
5
6
from fields import Fields
7
from six import string_types
8
9
from .actions import Action
10
from .event import Event
11
12
13
class Query(Fields.query):
14
    """
15
    A query class.
16
17
    See :class:`hunter.Event` for fields that can be filtered on.
18
    """
19
    query = ()
20
    allowed = tuple(i for i in Event.__dict__.keys() if not i.startswith('_'))
21
22
    def __init__(self, **query):
23
        """
24
        Args:
25
            query: criteria to match on.
26
27
                Accepted arguments: ``arg``, ``code``, ``filename``, ``frame``, ``fullsource``, ``function``,
28
                ``globals``, ``kind``, ``lineno``, ``locals``, ``module``, ``source``, ``stdlib``, ``tracer``.
29
        """
30
        for key in query:
31
            if key not in self.allowed:
32
                raise TypeError("Unexpected argument {!r}. Must be one of {}.".format(key, self.allowed))
33
        self.query = query
34
35
    def __str__(self):
36
        return "Query(%s)" % (
37
            ', '.join("%s=%r" % item for item in self.query.items()),
38
        )
39
40
    def __repr__(self):
41
        return "<hunter._predicates.Query: query=%r>" % self.query
42
43
    def __call__(self, event):
44
        """
45
        Handles event. Returns True if all criteria matched.
46
        """
47
        for key, value in self.query.items():
48
            evalue = event[key]
49
            if isinstance(evalue, string_types) and isinstance(value, (list, tuple, set)):
50
                if not evalue.startswith(tuple(value)):
51
                    return False
52
            elif evalue != value:
53
                return False
54
55
        return True
56
57
    def __or__(self, other):
58
        """
59
        Convenience API so you can do ``Q() | Q()``. It converts that to ``Or(Q(), Q())``.
60
        """
61
        return Or(self, other)
62
63
    def __and__(self, other):
64
        """
65
        Convenience API so you can do ``Q() & Q()``. It converts that to ``And(Q(), Q())``.
66
        """
67
        return And(self, other)
68
69
    def __invert__(self):
70
        return Not(self)
71
72
73
class When(Fields.condition.actions):
74
    """
75
    Runs ``actions`` when ``condition(event)`` is ``True``.
76
77
    Actions take a single ``event`` argument.
78
    """
79
80
    def __init__(self, condition, *actions):
81
        if not actions:
82
            raise TypeError("Must give at least one action.")
83
        super(When, self).__init__(condition, [
84
            action() if inspect.isclass(action) and issubclass(action, Action) else action
85
            for action in actions
86
            ])
87
88
    def __str__(self):
89
        return "When(%s, %s)" % (
90
            self.condition,
91
            ', '.join(repr(p) for p in self.actions)
92
        )
93
94
    def __repr__(self):
95
        return "<hunter._predicates.When: condition=%r, actions=%r>" % (self.condition, self.actions)
96
97
    def __call__(self, event):
98
        """
99
        Handles the event.
100
        """
101
        if self.condition(event):
102
            for action in self.actions:
103
                action(event)
104
105
            return True
106
        return False
107
108
    def __or__(self, other):
109
        return Or(self, other)
110
111
    def __and__(self, other):
112
        return And(self, other)
113
114
115
class And(Fields.predicates):
116
    """
117
    `And` predicate. Exits at the first sub-predicate that returns ``False``.
118
    """
119
120
    def __init__(self, *predicates):
121
        self.predicates = predicates
122
123
    def __str__(self):
124
        return "And(%s)" % ', '.join(str(p) for p in self.predicates)
125
126
    def __repr__(self):
127
        return "<hunter._predicates.And: predicates=%r>" % (self.predicates,)
128
129
    def __call__(self, event):
130
        """
131
        Handles the event.
132
        """
133
        for predicate in self.predicates:
134
            if not predicate(event):
135
                return False
136
        return True
137
138
    def __or__(self, other):
139
        return Or(self, other)
140
141
    def __and__(self, other):
142
        return And(*chain(self.predicates, other.predicates if isinstance(other, And) else (other,)))
143
144
    def __invert__(self):
145
        return Not(self)
146
147
148
class Or(Fields.predicates):
149
    """
150
    `Or` predicate. Exits at first sub-predicate that returns ``True``.
151
    """
152
153
    def __init__(self, *predicates):
154
        self.predicates = predicates
155
156
    def __str__(self):
157
        return "Or(%s)" % ', '.join(str(p) for p in self.predicates)
158
159
    def __repr__(self):
160
        return "<hunter._predicates.Or: predicates=%r>" % (self.predicates,)
161
162
    def __call__(self, event):
163
        """
164
        Handles the event.
165
        """
166
        for predicate in self.predicates:
167
            if predicate(event):
168
                return True
169
        return False
170
171
    def __or__(self, other):
172
        return Or(*chain(self.predicates, other.predicates if isinstance(other, Or) else (other,)))
173
174
    def __and__(self, other):
175
        return And(self, other)
176
177
    def __invert__(self):
178
        return Not(self)
179
180
181
class Not(Fields.predicate):
182
    """
183
    `Not` predicate.
184
    """
185
186
    def __str__(self):
187
        return "Not(%s)" % self.predicate
188
189
    def __repr__(self):
190
        return "<hunter._predicates.Not: predicate=%r>" % self.predicate
191
192
    def __call__(self, event):
193
        """
194
        Handles the event.
195
        """
196
        return not self.predicate(event)
197
198
    def __or__(self, other):
199
        if isinstance(other, Not):
200
            return Not(And(self.predicate, other.predicate))
201
        return Or(self, other)
202
203
    def __and__(self, other):
204
        if isinstance(other, Not):
205
            return Not(Or(self.predicate, other.predicate))
206
        return And(self, other)
207
208
    def __invert__(self):
209
        return self.predicate
210