def test_single_rule_depending_on_subject_selection(self): rules = [ (Exactly(A), (Select(SubA),), noop) ] subgraph = self.create_subgraph(A, rules, SubA()) self.assert_equal_with_printing(dedent(""" digraph { // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] "Select(A) for SubA" -> {"(A, (Select(SubA),), noop) of SubA"} // internal entries "(A, (Select(SubA),), noop) of SubA" -> {"SubjectIsProduct(SubA)"} }""").strip(), subgraph)
def test_secondary_select_projection_failure(self): rules = _suba_root_rules + [ TaskRule(Exactly(A), [SelectProjection(B, D, 'some', C)], noop), TaskRule(C, [], noop) ] validator = self.create_validator({}, rules) with self.assertRaises(ValueError) as cm: validator.assert_ruleset_valid() self.assert_equal_with_printing(dedent(""" Rules with errors: 1 (A, (SelectProjection(B, D, 'some', C),), noop): no matches for Select(B) when resolving SelectProjection(B, D, 'some', C) with subject types: D """).strip(), str(cm.exception))
def test_select_dependencies_non_matching_subselector_because_of_intrinsic(self): rules = [ (Exactly(A), (SelectDependencies(B, SubA, field_types=(D,)),), noop), ] intrinsics = [ (C, B, noop), ] graphmaker = GraphMaker(NodeBuilder.create(rules, intrinsics), root_subject_fns=_suba_root_subject_fns) subgraph = graphmaker.generate_subgraph(SubA(), requested_product=A) self.assert_equal_with_printing('{empty graph}', subgraph) self.assert_equal_with_printing(dedent(""" Rules with errors: 1 (Exactly(A), (SelectDependencies(B, SubA, u'dependencies', field_types=(D,)),), noop): no matches for Select(B) when resolving SelectDependencies(B, SubA, u'dependencies', field_types=(D,)) with subject types: D""").strip(), subgraph.error_message())
def test_one_level_of_recursion(self): rules = [ (Exactly(A), (Select(B),), noop), (B, (Select(SubA),), noop) ] graphmaker = GraphMaker(NodeBuilder.create(rules, tuple()), root_subject_fns=_suba_root_subject_fns) subgraph = graphmaker.generate_subgraph(SubA(), requested_product=A) self.assert_equal_with_printing(dedent(""" { root_subject_types: (SubA,) root_rules: (Exactly(A), (Select(B),), noop) of SubA (B, (Select(SubA),), noop) of SubA => (SubjectIsProduct(SubA),) (Exactly(A), (Select(B),), noop) of SubA => ((B, (Select(SubA),), noop) of SubA,) }""").strip(), subgraph)
def test_initial_select_projection_failure(self): rules = [ (Exactly(A), (SelectProjection(B, D, ('some',), C),), noop), ] validator = RulesetValidator(NodeBuilder.create(rules, tuple()), goal_to_product={}, root_subject_fns=_suba_root_subject_fns) with self.assertRaises(ValueError) as cm: validator.validate() self.assert_equal_with_printing(dedent(""" Rules with errors: 1 (Exactly(A), (SelectProjection(B, D, (u'some',), C),), noop): no matches for Select(C) when resolving SelectProjection(B, D, (u'some',), C) with subject types: SubA """).strip(), str(cm.exception))
class JvmAppAdaptor(TargetAdaptor): def __init__(self, bundles=None, **kwargs): """ :param list bundles: A list of `BundleAdaptor` objects """ super(JvmAppAdaptor, self).__init__(**kwargs) self.bundles = bundles @addressable_list(Exactly(BundleAdaptor)) def bundles(self): """The BundleAdaptors for this JvmApp.""" return self.bundles @property def field_adaptors(self): with exception_logging(logger, 'Exception in `field_adaptors` property'): field_adaptors = super(JvmAppAdaptor, self).field_adaptors if getattr(self, 'bundles', None) is None: return field_adaptors # Construct a field for the `bundles` argument. filespecs_list = [] path_globs_list = [] excluded_path_globs_list = [] for bundle in self.bundles: # Short circuit in the case of `bundles=[..., bundle(), ...]`. if not hasattr(bundle, 'fileset'): # N.B. This notice is duplicated in jvm_app.py::Bundle.__call__() for the old engine. deprecated_conditional( lambda: True, '1.2.0', 'bare bundle() without `fileset=` param', "Pass a `fileset=` parameter: `bundle(fileset=globs('*.config')`" ) logger.warn( 'Ignoring `bundle()` without `fileset` parameter.') continue base_globs = BaseGlobs.from_sources_field(bundle.fileset) filespecs_list.append(base_globs.filespecs) path_globs, excluded_path_globs = base_globs.to_path_globs( self.address.spec_path) path_globs_list.append(path_globs) excluded_path_globs_list.append(excluded_path_globs) bundles_field = BundlesField(self.address, self.bundles, filespecs_list, path_globs_list, excluded_path_globs_list) return field_adaptors + (bundles_field, )
def test_select_projection_simple(self): rules = [ (Exactly(A), (SelectProjection(B, D, ('some',), SubA),), noop), (B, (Select(D),), noop), ] graphmaker = GraphMaker(NodeBuilder.create(rules, tuple()), root_subject_fns=_suba_root_subject_fns) subgraph = graphmaker.generate_subgraph(SubA(), requested_product=A) self.assert_equal_with_printing(dedent(""" { root_subject_types: (SubA,) root_rules: (Exactly(A), (SelectProjection(B, D, (u'some',), SubA),), noop) of SubA (B, (Select(D),), noop) of D => (SubjectIsProduct(D),) (Exactly(A), (SelectProjection(B, D, (u'some',), SubA),), noop) of SubA => (SubjectIsProduct(SubA), (B, (Select(D),), noop) of D,) }""").strip(), subgraph)
def test_select_dependencies_with_subject_as_first_subselector(self): rules = [ (Exactly(A), (SelectDependencies(B, SubA, field_types=(D,)),), noop), (B, (Select(D),), noop), ] graphmaker = GraphMaker(NodeBuilder.create(rules, tuple()), root_subject_fns=_suba_root_subject_fns) subgraph = graphmaker.generate_subgraph(SubA(), requested_product=A) self.assert_equal_with_printing(dedent(""" { root_subject_types: (SubA,) root_rules: (Exactly(A), (SelectDependencies(B, SubA, u'dependencies', field_types=(D,)),), noop) of SubA (B, (Select(D),), noop) of D => (SubjectIsProduct(D),) (Exactly(A), (SelectDependencies(B, SubA, u'dependencies', field_types=(D,)),), noop) of SubA => (SubjectIsProduct(SubA), (B, (Select(D),), noop) of D,) }""").strip(), subgraph)
def test_multiple_selects(self): rules = [(Exactly(A), (Select(SubA), Select(B)), noop), (B, tuple(), noop)] graphmaker = GraphMaker(RuleIndex.create(rules, tuple()), root_subject_fns=_suba_root_subject_fns) subgraph = graphmaker.generate_subgraph(SubA(), requested_product=A) self.assert_equal_with_printing( dedent(""" { root_subject_types: (SubA,) root_rules: Select(A) for SubA => ((Exactly(A), (Select(SubA), Select(B)), noop) of SubA,) all_rules: (B, (), noop) of SubA => (,) (Exactly(A), (Select(SubA), Select(B)), noop) of SubA => (SubjectIsProduct(SubA), (B, (), noop) of SubA,) }""").strip(), subgraph)
def test_one_level_of_recursion(self): rules = [ TaskRule(Exactly(A), [Select(B)], noop), TaskRule(B, [Select(SubA)], noop) ] subgraph = self.create_subgraph(A, rules, SubA()) self.assert_equal_with_printing( dedent(""" digraph { // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] "Select(A) for SubA" -> {"(A, (Select(B),), noop) of SubA"} // internal entries "(A, (Select(B),), noop) of SubA" -> {"(B, (Select(SubA),), noop) of SubA"} "(B, (Select(SubA),), noop) of SubA" -> {"SubjectIsProduct(SubA)"} }""").strip(), subgraph)
def test_successful_when_one_field_type_is_unfulfillable(self): # NB We may want this to be a warning, since it may not be intentional rules = [ (B, (Select(SubA),), noop), (D, (Select(Exactly(B)), SelectDependencies(B, SubA, field_types=(SubA, C))), noop) ] graphmaker = GraphMaker(NodeBuilder.create(rules, tuple()), root_subject_fns=_suba_root_subject_fns) subgraph = graphmaker.generate_subgraph(SubA(), requested_product=D) self.assert_equal_with_printing(dedent(""" { root_subject_types: (SubA,) root_rules: (D, (Select(Exactly(B)), SelectDependencies(B, SubA, u'dependencies', field_types=(SubA, C,))), noop) of SubA (B, (Select(SubA),), noop) of SubA => (SubjectIsProduct(SubA),) (D, (Select(Exactly(B)), SelectDependencies(B, SubA, u'dependencies', field_types=(SubA, C,))), noop) of SubA => ((B, (Select(SubA),), noop) of SubA, SubjectIsProduct(SubA), (B, (Select(SubA),), noop) of SubA,) }""").strip(), subgraph)
class JvmAppAdaptor(TargetAdaptor): def __init__(self, bundles=None, **kwargs): """ :param list bundles: A list of `BundleAdaptor` objects """ super(JvmAppAdaptor, self).__init__(**kwargs) self.bundles = bundles @addressable_list(Exactly(BundleAdaptor)) def bundles(self): """The BundleAdaptors for this JvmApp.""" return self.bundles @property def field_adaptors(self): with exception_logging(logger, 'Exception in `field_adaptors` property'): field_adaptors = super(JvmAppAdaptor, self).field_adaptors if getattr(self, 'bundles', None) is None: return field_adaptors bundles_field = self._construct_bundles_field() return field_adaptors + (bundles_field,) def _construct_bundles_field(self): filespecs_list = [] path_globs_list = [] excluded_path_globs_list = [] for bundle in self.bundles: # NB: if a bundle has a rel_path, then the rel_root of the resulting file globs must be # set to that rel_path. rel_root = getattr(bundle, 'rel_path', self.address.spec_path) base_globs = BaseGlobs.from_sources_field(bundle.fileset, rel_root) path_globs, excluded_path_globs = base_globs.to_path_globs(rel_root) filespecs_list.append(base_globs.filespecs) path_globs_list.append(path_globs) excluded_path_globs_list.append(excluded_path_globs) return BundlesField(self.address, self.bundles, filespecs_list, path_globs_list, excluded_path_globs_list)
def test_multiple_selects(self): rules = [ (Exactly(A), (Select(SubA), Select(B)), noop), (B, tuple(), noop) ] subgraph = self.create_subgraph(A, rules, SubA()) self.assert_equal_with_printing(dedent(""" digraph { // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] "Select(A) for SubA" -> {"(A, (Select(SubA), Select(B)), noop) of SubA"} // internal entries "(A, (Select(SubA), Select(B)), noop) of SubA" -> {"SubjectIsProduct(SubA)" "(B, (,), noop) of SubA"} "(B, (,), noop) of SubA" -> {} }""").strip(), subgraph)
def test_select_projection_simple(self): rules = [ TaskRule(Exactly(A), [SelectProjection(B, D, 'some', SubA)], noop), TaskRule(B, [Select(D)], noop), ] subgraph = self.create_subgraph(A, rules, SubA()) self.assert_equal_with_printing( dedent(""" digraph { // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] "Select(A) for SubA" -> {"(A, (SelectProjection(B, D, 'some', SubA),), noop) of SubA"} // internal entries "(A, (SelectProjection(B, D, 'some', SubA),), noop) of SubA" -> {"SubjectIsProduct(SubA)" "(B, (Select(D),), noop) of D"} "(B, (Select(D),), noop) of D" -> {"SubjectIsProduct(D)"} }""").strip(), subgraph)
def test_select_dependencies_with_matching_singleton(self): rules = [ TaskRule(Exactly(A), [SelectDependencies(B, SubA, field_types=(C,))], noop), SingletonRule(B, B()), ] subgraph = self.create_subgraph(A, rules, SubA()) #TODO perhaps singletons should be marked in the dot format somehow self.assert_equal_with_printing(dedent(""" digraph { // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] "Select(A) for SubA" -> {"(A, (SelectDependencies(B, SubA, field_types=(C,)),), noop) of SubA"} // internal entries "(A, (SelectDependencies(B, SubA, field_types=(C,)),), noop) of SubA" -> {"SubjectIsProduct(SubA)" "Singleton(B(), B)"} }""").strip(), subgraph)
def test_select_dependencies_with_subject_as_first_subselector(self): rules = [ TaskRule(Exactly(A), [SelectDependencies(B, SubA, field_types=(D,))], noop), TaskRule(B, [Select(D)], noop), ] subgraph = self.create_subgraph(A, rules, SubA()) self.assert_equal_with_printing(dedent(""" digraph { // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] "Select(A) for SubA" -> {"(A, (SelectDependencies(B, SubA, field_types=(D,)),), noop) of SubA"} // internal entries "(A, (SelectDependencies(B, SubA, field_types=(D,)),), noop) of SubA" -> {"SubjectIsProduct(SubA)" "(B, (Select(D),), noop) of D"} "(B, (Select(D),), noop) of D" -> {"SubjectIsProduct(D)"} }""").strip(), subgraph)
def test_successful_when_one_field_type_is_unfulfillable(self): # NB We may want this to be a warning, since it may not be intentional rules = [ TaskRule(B, [Select(SubA)], noop), TaskRule(D, [Select(Exactly(B)), SelectDependencies(B, SubA, field_types=(SubA, C))], noop) ] subgraph = self.create_subgraph(D, rules, SubA()) self.assert_equal_with_printing(dedent(""" digraph { // root subject types: SubA // root entries "Select(D) for SubA" [color=blue] "Select(D) for SubA" -> {"(D, (Select(B), SelectDependencies(B, SubA, field_types=(SubA, C,))), noop) of SubA"} // internal entries "(B, (Select(SubA),), noop) of SubA" -> {"SubjectIsProduct(SubA)"} "(D, (Select(B), SelectDependencies(B, SubA, field_types=(SubA, C,))), noop) of SubA" -> {"(B, (Select(SubA),), noop) of SubA" "SubjectIsProduct(SubA)"} }""").strip(), subgraph)
def test_select_dependencies_with_separate_types_for_subselectors(self): rules = [(Exactly(A), (SelectDependencies(B, C, field_types=(D, )), ), noop), (B, (Select(D), ), noop), (C, (Select(SubA), ), noop)] graphmaker = GraphMaker(RuleIndex.create(rules, tuple()), root_subject_fns=_suba_root_subject_fns) subgraph = graphmaker.generate_subgraph(SubA(), requested_product=A) self.assert_equal_with_printing( dedent(""" { root_subject_types: (SubA,) root_rules: Select(A) for SubA => ((Exactly(A), (SelectDependencies(B, C, field_types=(D,)),), noop) of SubA,) all_rules: (B, (Select(D),), noop) of D => (SubjectIsProduct(D),) (C, (Select(SubA),), noop) of SubA => (SubjectIsProduct(SubA),) (Exactly(A), (SelectDependencies(B, C, field_types=(D,)),), noop) of SubA => ((C, (Select(SubA),), noop) of SubA, (B, (Select(D),), noop) of D,) }""").strip(), subgraph)
def test_select_dependencies_with_matching_intrinsic(self): rules = [ (Exactly(A), (SelectDependencies(B, SubA, field_types=(C,)),), noop), ] intrinsics = [ (B, C, noop), ] graphmaker = GraphMaker(NodeBuilder.create(rules, intrinsics), root_subject_fns=_suba_root_subject_fns) subgraph = graphmaker.generate_subgraph(SubA(), requested_product=A) self.assert_equal_with_printing(dedent(""" { root_subject_types: (SubA,) root_rules: (Exactly(A), (SelectDependencies(B, SubA, u'dependencies', field_types=(C,)),), noop) of SubA (Exactly(A), (SelectDependencies(B, SubA, u'dependencies', field_types=(C,)),), noop) of SubA => (SubjectIsProduct(SubA), IntrinsicRule(noop) of C,) IntrinsicRule(noop) of C => (,) }""").strip(), subgraph)
def __new__(cls, output_type, input_selectors, func): # Validate result type. if isinstance(output_type, Exactly): constraint = output_type elif isinstance(output_type, type): constraint = Exactly(output_type) else: raise TypeError( "Expected an output_type for rule `{}`, got: {}".format( func.__name__, output_type)) # Validate selectors. if not isinstance(input_selectors, list): raise TypeError( "Expected a list of Selectors for rule `{}`, got: {}".format( func.__name__, type(input_selectors))) # Create. return super(TaskRule, cls).__new__(cls, constraint, tuple(input_selectors), func)
def test_select_transitive_with_separate_types_for_subselectors(self): rules = [ TaskRule(Exactly(A), [SelectTransitive(B, C, field_types=(D,))], noop), TaskRule(B, [Select(D)], noop), TaskRule(C, [Select(SubA)], noop) ] subgraph = self.create_subgraph(A, rules, SubA()) self.assert_equal_with_printing(dedent(""" digraph { // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] "Select(A) for SubA" -> {"(A, (SelectTransitive(B, C, field_types=(D,)),), noop) of SubA"} // internal entries "(A, (SelectTransitive(B, C, field_types=(D,)),), noop) of SubA" -> {"(C, (Select(SubA),), noop) of SubA" "(B, (Select(D),), noop) of D"} "(B, (Select(D),), noop) of D" -> {"SubjectIsProduct(D)"} "(C, (Select(SubA),), noop) of SubA" -> {"SubjectIsProduct(SubA)"} }""").strip(), subgraph)
def test_select_dependencies_multiple_field_types_all_resolvable_with_deps(self): rules = [ (Exactly(A), (SelectDependencies(B, SubA, field_types=(C, D,)),), noop), # for the C type, it'll just be a literal, but for D, it'll traverse one more edge (B, (Select(C),), noop), (C, (Select(D),), noop), ] graphmaker = GraphMaker(NodeBuilder.create(rules, tuple()), root_subject_fns=_suba_root_subject_fns) subgraph = graphmaker.generate_subgraph(SubA(), requested_product=A) self.assert_equal_with_printing(dedent(""" { root_subject_types: (SubA,) root_rules: (Exactly(A), (SelectDependencies(B, SubA, u'dependencies', field_types=(C, D,)),), noop) of SubA (B, (Select(C),), noop) of C => (SubjectIsProduct(C),) (B, (Select(C),), noop) of D => ((C, (Select(D),), noop) of D,) (C, (Select(D),), noop) of D => (SubjectIsProduct(D),) (Exactly(A), (SelectDependencies(B, SubA, u'dependencies', field_types=(C, D,)),), noop) of SubA => (SubjectIsProduct(SubA), (B, (Select(C),), noop) of C, (B, (Select(C),), noop) of D,) }""").strip(), subgraph)
def test_select_dependencies_multiple_field_types_all_resolvable_with_deps(self): rules = [ TaskRule(Exactly(A), [SelectDependencies(B, SubA, field_types=(C, D,))], noop), # for the C type, it'll just be a literal, but for D, it'll traverse one more edge TaskRule(B, [Select(C)], noop), TaskRule(C, [Select(D)], noop), ] subgraph = self.create_subgraph(A, rules, SubA()) self.assert_equal_with_printing(dedent(""" digraph { // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] "Select(A) for SubA" -> {"(A, (SelectDependencies(B, SubA, field_types=(C, D,)),), noop) of SubA"} // internal entries "(A, (SelectDependencies(B, SubA, field_types=(C, D,)),), noop) of SubA" -> {"SubjectIsProduct(SubA)" "(B, (Select(C),), noop) of C" "(B, (Select(C),), noop) of D"} "(B, (Select(C),), noop) of C" -> {"SubjectIsProduct(C)"} "(B, (Select(C),), noop) of D" -> {"(C, (Select(D),), noop) of D"} "(C, (Select(D),), noop) of D" -> {"SubjectIsProduct(D)"} }""").strip(), subgraph)
def test_select_dependencies_with_matching_intrinsic(self): rules = [ (Exactly(A), (SelectDependencies(B, SubA, field_types=(C,)),), noop), ] intrinsics = [ (B, C, noop), ] subgraph = self.create_subgraph_with_intrinsics(intrinsics, A, rules, SubA(), _suba_root_subject_types) #TODO perhaps intrinsics should be marked in the dot format somehow self.assert_equal_with_printing(dedent(""" digraph { // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] "Select(A) for SubA" -> {"(A, (SelectDependencies(B, SubA, field_types=(C,)),), noop) of SubA"} // internal entries "(A, (SelectDependencies(B, SubA, field_types=(C,)),), noop) of SubA" -> {"SubjectIsProduct(SubA)" "(B, (Select(C),), noop) of C"} "(B, (Select(C),), noop) of C" -> {"SubjectIsProduct(C)"} }""").strip(), subgraph)
def test_none(self): with self.assertRaises(ValueError): Exactly()
def constraint(cls): """Returns the typeconstraint for the symbol table""" # NB Sort types so that multiple calls get the same tuples. symbol_table_types = sorted(set(cls.table().values())) return Exactly(*symbol_table_types, description='symbol table types')
from pants.base.specs import (AscendantAddresses, DescendantAddresses, SiblingAddresses, SingleAddress) from pants.build_graph.address import Address, BuildFileAddress from pants.engine.addressable import (AddressableDescriptor, BuildFileAddresses, Collection, Exactly, TypeConstraintError) from pants.engine.fs import FilesContent, PathGlobs, Snapshot from pants.engine.mapper import AddressFamily, AddressMap, AddressMapper, ResolveError from pants.engine.objects import Locatable, SerializableFactory, Validatable from pants.engine.rules import RootRule, SingletonRule, TaskRule, rule from pants.engine.selectors import Select, SelectDependencies, SelectProjection from pants.engine.struct import Struct from pants.util.objects import datatype _SPECS_CONSTRAINT = Exactly(SingleAddress, SiblingAddresses, DescendantAddresses, AscendantAddresses) class ResolvedTypeMismatchError(ResolveError): """Indicates a resolved object was not of the expected type.""" def _key_func(entry): key, value = entry return key class BuildDirs(datatype('BuildDirs', ['dependencies'])): """A list of Stat objects for directories containing build files."""
def path_globs(self): """Creates a `PathGlobs` object for the files held by these Sources. This field may be projected to request the content of the files for this Sources object. """ return PathGlobs.create(Files, self.spec_path, files=self.files, globs=self.globs, rglobs=self.rglobs, zglobs=self.zglobs) @abstractproperty def extensions(self): """A collection of file extensions collected by this Sources instance. An empty collection indicates that any extension will be accepted. """ @property def excludes(self): """The sources to exclude. :rtype: :class:`Sources` """ # Since Sources.excludes is recursive on the Sources type, we need to post-class-definition # re-define excludes in this way. Sources.excludes = addressable(Exactly(Sources))(Sources.excludes)
def test_disallows_unsplatted_lists(self): with self.assertRaises(TypeError): Exactly([1])
def create(cls, task_entries, intrinsic_entries=None, singleton_entries=None): """Creates a NodeBuilder with tasks indexed by their output type.""" intrinsic_entries = intrinsic_entries or tuple() singleton_entries = singleton_entries or tuple() # NB make tasks ordered so that gen ordering is deterministic. serializable_tasks = OrderedDict() def add_task(product_type, rule): if product_type not in serializable_tasks: serializable_tasks[product_type] = OrderedSet() serializable_tasks[product_type].add(rule) for entry in task_entries: if isinstance(entry, Rule): add_task(entry.output_product_type, entry) elif isinstance(entry, (tuple, list)) and len(entry) == 3: output_type, input_selectors, task = entry if isinstance(output_type, Exactly): constraint = output_type elif isinstance(output_type, type): constraint = Exactly(output_type) else: raise TypeError( "Unexpected product_type type {}, for rule {}".format( output_type, entry)) factory = TaskRule(tuple(input_selectors), task, output_type, constraint) # TODO: The heterogenity here has some confusing implications here: # see https://github.com/pantsbuild/pants/issues/4005 for kind in constraint.types: # NB Ensure that interior types from SelectDependencies / SelectProjections work by # indexing on the list of types in the constraint. add_task(kind, factory) add_task(constraint, factory) else: raise TypeError( "Unexpected rule type: {}." " Rules either extend Rule, or are 3 elem tuples.".format( type(entry))) intrinsics = dict() for output_type, input_type, func in intrinsic_entries: key = (input_type, output_type) if key in intrinsics: raise ValueError( 'intrinsic provided by {} has already been provided by: {}' .format(func.__name__, intrinsics[key])) intrinsics[key] = IntrinsicRule(input_type, output_type, func) singletons = dict() for output_type, func in singleton_entries: if output_type in singletons: raise ValueError( 'singleton provided by {} has already been provided by: {}' .format(func.__name__, singletons[output_type])) singletons[output_type] = SingletonRule(output_type, func) return cls(serializable_tasks, intrinsics, singletons)