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
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
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')
27 # gets a Change object, returns boolean
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):
40 if x
is not None and type(x
) is not types
.ListType
:
43 def mklist_br(x
): # branch needs to be handled specially
46 if type(x
) is not types
.ListType
:
50 if r
is not None and not hasattr(r
, 'match'):
54 self
.filter_fn
= filter_fn
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
):
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
:
69 if filt_re
is not None and (chg_val
is None or not filt_re
.match(chg_val
)):
71 if filt_fn
is not None and not filt_fn(chg_val
):
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
))