Changelog update.
[debian_buildbot.git] / master / buildbot / schedulers / filter.py
blob4db64ef2a68e12766e77d674f27a78ee60fbf342
1 # This file is part of Buildbot. Buildbot is free software: you can
2 # redistribute it and/or modify it under the terms of the GNU General Public
3 # License as published by the Free Software Foundation, version 2.
5 # This program is distributed in the hope that it will be useful, but WITHOUT
6 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
7 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
8 # details.
10 # You should have received a copy of the GNU General Public License along with
11 # this program; if not, write to the Free Software Foundation, Inc., 51
12 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
14 # Copyright Buildbot Team Members
16 import re, types
18 from buildbot.util import ComparableMixin, NotABranch
20 class ChangeFilter(ComparableMixin):
22 # TODO: filter_fn will always be different. Does that mean that we always
23 # reconfigure schedulers? Is that a problem?
24 compare_attrs = ('filter_fn', 'checks')
26 def __init__(self,
27 # gets a Change object, returns boolean
28 filter_fn=None,
29 # change attribute comparisons: exact match to PROJECT, member of
30 # list PROJECTS, regular expression match to PROJECT_RE, or
31 # PROJECT_FN returns True when called with the project; repository,
32 # branch, and so on are similar. Note that the regular expressions
33 # are anchored to the first character of the string. For convenience,
34 # a list can also be specified to the singular option (e.g,. PROJETS
35 project=None, project_re=None, project_fn=None,
36 repository=None, repository_re=None, repository_fn=None,
37 branch=NotABranch, branch_re=None, branch_fn=None,
38 category=None, category_re=None, category_fn=None):
39 def mklist(x):
40 if x is not None and type(x) is not types.ListType:
41 return [ x ]
42 return x
43 def mklist_br(x): # branch needs to be handled specially
44 if x is NotABranch:
45 return None
46 if type(x) is not types.ListType:
47 return [ x ]
48 return x
49 def mkre(r):
50 if r is not None and not hasattr(r, 'match'):
51 r = re.compile(r)
52 return r
54 self.filter_fn = filter_fn
55 self.checks = [
56 (mklist(project), mkre(project_re), project_fn, "project"),
57 (mklist(repository), mkre(repository_re), repository_fn, "repository"),
58 (mklist_br(branch), mkre(branch_re), branch_fn, "branch"),
59 (mklist(category), mkre(category_re), category_fn, "category"),
62 def filter_change(self, change):
63 if self.filter_fn is not None and not self.filter_fn(change):
64 return False
65 for (filt_list, filt_re, filt_fn, chg_attr) in self.checks:
66 chg_val = getattr(change, chg_attr, '')
67 if filt_list is not None and chg_val not in filt_list:
68 return False
69 if filt_re is not None and (chg_val is None or not filt_re.match(chg_val)):
70 return False
71 if filt_fn is not None and not filt_fn(chg_val):
72 return False
73 return True
75 def __repr__(self):
76 checks = []
77 for (filt_list, filt_re, filt_fn, chg_attr) in self.checks:
78 if filt_list is not None and len(filt_list) == 1:
79 checks.append('%s == %s' % (chg_attr, filt_list[0]))
80 elif filt_list is not None:
81 checks.append('%s in %r' % (chg_attr, filt_list))
82 if filt_re is not None :
83 checks.append('%s ~/%s/' % (chg_attr, filt_re))
84 if filt_fn is not None :
85 checks.append('%s(%s)' % (filt_fn.__name__, chg_attr))
87 return "<%s on %s>" % (self.__class__.__name__, ' and '.join(checks))