OLD | NEW |
---|---|
(Empty) | |
1 # Copyright 2016 The LUCI Authors. All rights reserved. | |
2 # Use of this source code is governed under the Apache License, Version 2.0 | |
3 # that can be found in the LICENSE file. | |
martiniss
2016/10/03 19:14:19
Add a file doc string and tests?
| |
4 | |
5 import re | |
6 | |
7 from collections import defaultdict, OrderedDict | |
8 | |
9 | |
10 class _filterObject(object): | |
11 def __init__(self, data, re_data): | |
12 self.data = data | |
13 self.re_data = re_data | |
14 | |
15 def __call__(self, check, step_odict): | |
16 includes = self.data.copy() | |
17 re_data = self.re_data.copy() | |
18 | |
19 re_usage_count = defaultdict(int) | |
20 | |
21 to_ret = OrderedDict() | |
22 for name, step in step_odict.iteritems(): | |
23 field_set = includes.pop(name, None) | |
24 if not field_set: | |
dnj
2016/10/04 16:42:33
Can we have an error if both specific and regex ma
dnj
2016/10/04 16:42:34
nit: You're using "is None" below, but "not" here.
iannucci
2016/10/06 20:28:08
I don't think that's an error case, I've documente
iannucci
2016/10/06 20:28:09
Done.
| |
25 for exp, (_, _, fset) in re_data.iteritems(): | |
26 if exp.match(name): | |
27 re_usage_count[exp] += 1 | |
28 field_set = fset | |
29 break | |
30 if field_set is None: | |
31 continue | |
32 if len(field_set) == 0: | |
33 to_ret[name] = step | |
34 else: | |
35 to_ret[name] = { | |
36 k: v for k, v in step.iteritems() | |
37 if k in field_set or k == 'name' | |
38 } | |
39 | |
40 check('all includes were used', len(includes) == 0) | |
41 | |
42 for regex, (at_least, at_most, _) in re_data.iteritems(): | |
43 check(re_usage_count[regex] >= at_least) | |
44 if at_most is not None: | |
45 check(re_usage_count[regex] < at_most) | |
dnj
2016/10/04 16:42:34
If I say, "at most 3", I would expect 3 to be vali
iannucci
2016/10/06 20:28:09
Done.
| |
46 | |
47 return to_ret | |
48 | |
49 def include(self, step_name, *fields): | |
50 new_data = self.data.copy() | |
51 new_data[step_name] = set(fields) | |
52 return _filterObject(new_data, self.re_data) | |
53 | |
54 def include_re(self, step_name_re, at_least=1, at_most=None, *fields): | |
55 new_re_data = self.re_data.copy() | |
56 new_re_data[re.compile(step_name_re)] = (at_least, at_most, set(fields)) | |
dnj
2016/10/04 16:42:34
Let's use a namedtuple here. Simple to create one
iannucci
2016/10/06 20:28:08
Done.
| |
57 return _filterObject(self.data, new_re_data) | |
58 | |
59 | |
60 def NewFilter(*steps): | |
dnj
2016/10/04 16:42:34
docstrings!
iannucci
2016/10/06 20:28:09
Done.
| |
61 return _filterObject({name: set() for name in steps}, {}) | |
62 | |
63 | |
64 def DoesntRun(check, step_odict, *steps): | |
dnj
2016/10/04 16:42:34
This looks awkward. How about DoesNotRun?
iannucci
2016/10/06 20:28:09
Done.
| |
65 banSet = set(steps) | |
66 for step_name in step_odict: | |
67 check(step_name not in banSet) | |
68 | |
69 | |
70 def DoesntRunRE(check, step_odict, *step_regexes): | |
dnj
2016/10/04 16:42:34
(same)
iannucci
2016/10/06 20:28:09
Done.
| |
71 step_regexes = [re.compile(r) for r in step_regexes] | |
dnj
2016/10/04 16:42:34
Assert that "step_odict" is an OrderedDict? Here a
iannucci
2016/10/06 20:28:09
That would be a terrible abstraction violation :D.
| |
72 for step_name in step_odict: | |
73 for r in step_regexes: | |
74 check(not r.match(step_name)) | |
75 | |
76 | |
77 def MustRun(check, step_odict, *steps): | |
78 step_names = step_odict.keys() | |
79 for step_name in steps: | |
80 check(step_name in step_names) | |
81 | |
82 | |
83 def MustRunRE(check, step_odict, step_regex, at_least=1, at_most=None): | |
martiniss
2016/10/03 19:14:18
Maybe have examples of these in other engine tests
iannucci
2016/10/06 20:28:09
there are docs now, I don't think an example of ev
| |
84 step_regex = re.compile(step_regex) | |
dnj
2016/10/04 16:42:34
WDYT about allowing "step_regex" to actually be a
iannucci
2016/10/06 20:28:08
It's already the case.
f = re.compile('foo')
F
| |
85 matches = 0 | |
86 for step_name in step_odict: | |
87 if step_regex.match(step_name): | |
88 matches += 1 | |
89 check(matches >= at_least) | |
90 if at_most is not None: | |
91 check(matches < at_most) | |
92 | |
93 | |
94 def DropExpectation(_check, _step_odict): | |
95 return [] | |
OLD | NEW |