Bug 1336559 - Refactor keyed-by matching algorithm into standalone utility function, r?dustin
MozReview-Commit-ID: Jqyhbj7nC6z
--- a/taskcluster/taskgraph/util/attributes.py
+++ b/taskcluster/taskgraph/util/attributes.py
@@ -1,12 +1,15 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+import re
+
+
INTEGRATION_PROJECTS = set([
'mozilla-inbound',
'autoland',
])
RELEASE_PROJECTS = set([
'mozilla-central',
'mozilla-aurora',
@@ -33,16 +36,37 @@ def attrmatch(attributes, **kwargs):
elif callable(kwval):
if not kwval(attval):
return False
elif kwval != attributes[kwkey]:
return False
return True
+def keymatch(attributes, target):
+ """Determine if any keys in attributes are a match to target, then return
+ a list of matching values. First exact matches will be checked. Failing
+ that, regex matches and finally a default key.
+ """
+ # exact match
+ if target in attributes:
+ return [attributes[target]]
+
+ # regular expression match
+ matches = [v for k, v in attributes.iteritems() if re.match(k + '$', target)]
+ if matches:
+ return matches
+
+ # default
+ if 'default' in attributes:
+ return [attributes['default']]
+
+ return []
+
+
def match_run_on_projects(project, run_on_projects):
"""Determine whether the given project is included in the `run-on-projects`
parameter, applying expansions for things like "integration" mentioned in
the attribute documentation."""
if 'all' in run_on_projects:
return True
if 'integration' in run_on_projects:
if project in INTEGRATION_PROJECTS:
--- a/taskcluster/taskgraph/util/schema.py
+++ b/taskcluster/taskgraph/util/schema.py
@@ -1,19 +1,20 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from __future__ import absolute_import, print_function, unicode_literals
-import re
import copy
import pprint
import voluptuous
+from .attributes import keymatch
+
def validate_schema(schema, obj, msg_prefix):
"""
Validate that object satisfies schema. If not, generate a useful exception
beginning with msg_prefix.
"""
try:
# deep copy the result since it may include mutable defaults
@@ -107,32 +108,21 @@ def resolve_keyed_by(item, field, item_n
while True:
if not isinstance(value, dict) or len(value) != 1 or not value.keys()[0].startswith('by-'):
return item
keyed_by = value.keys()[0][3:] # strip off 'by-' prefix
key = extra_values.get(keyed_by) if keyed_by in extra_values else item[keyed_by]
alternatives = value.values()[0]
- # exact match
- if key in alternatives:
- value = container[subfield] = alternatives[key]
- continue
-
- # regular expression match
- matches = [(k, v) for k, v in alternatives.iteritems() if re.match(k + '$', key)]
+ matches = keymatch(alternatives, key)
if len(matches) > 1:
raise Exception(
"Multiple matching values for {} {!r} found while "
"determining item {} in {}".format(
keyed_by, key, field, item_name))
elif matches:
- value = container[subfield] = matches[0][1]
- continue
-
- # default
- if 'default' in alternatives:
- value = container[subfield] = alternatives['default']
+ value = container[subfield] = matches[0]
continue
raise Exception(
"No {} matching {!r} nor 'default' found while determining item {} in {}".format(
keyed_by, key, field, item_name))