def _register_task(self, tasks, output_type, rule: TaskRule, union_rules: Dict[Type, "OrderedSet[Type]"]) -> None: """Register the given TaskRule with the native scheduler.""" func = Function(self._to_key(rule.func)) self._native.lib.tasks_task_begin(tasks, func, self._to_type(output_type), rule.cacheable) for selector in rule.input_selectors: self._native.lib.tasks_add_select(tasks, self._to_type(selector)) anno = rule.annotations if anno.canonical_name: name = anno.canonical_name desc = anno.desc if anno.desc else "" self._native.lib.tasks_add_display_info(tasks, name.encode(), desc.encode()) def add_get_edge(product, subject): self._native.lib.tasks_add_get(tasks, self._to_type(product), self._to_type(subject)) for the_get in rule.input_gets: if union.is_instance(the_get.subject_declared_type): # If the registered subject type is a union, add Get edges to all registered union members. for union_member in union_rules.get( the_get.subject_declared_type, []): add_get_edge(the_get.product, union_member) else: # Otherwise, the Get subject is a "concrete" type, so add a single Get edge. add_get_edge(the_get.product, the_get.subject_declared_type) self._native.lib.tasks_task_end(tasks)
def _register_task(self, tasks, rule: TaskRule, union_membership: UnionMembership) -> None: """Register the given TaskRule with the native scheduler.""" self._native.lib.tasks_task_begin( tasks, rule.func, rule.output_type, issubclass(rule.output_type, EngineAwareReturnType), rule.cacheable, rule.canonical_name, rule.desc or "", rule.level.level, ) for selector in rule.input_selectors: self._native.lib.tasks_add_select(tasks, selector) def add_get_edge(product, subject): self._native.lib.tasks_add_get(tasks, product, subject) for the_get in rule.input_gets: if union.is_instance(the_get.input_type): # If the registered subject type is a union, add Get edges to all registered # union members. for union_member in union_membership.get(the_get.input_type): add_get_edge(the_get.output_type, union_member) else: # Otherwise, the Get subject is a "concrete" type, so add a single Get edge. add_get_edge(the_get.output_type, the_get.input_type) self._native.lib.tasks_task_end(tasks)
def _validate_input(self, input_: Any, *, shorthand_form: bool) -> _Input: if isinstance(input_, type): if shorthand_form: raise TypeError( "Invalid Get. Because you are using the shorthand form " "Get(OutputType, InputType(constructor args)), the second argument should be " f"a constructor call, rather than a type, but given {input_}." ) else: raise TypeError( "Invalid Get. Because you are using the longhand form " "Get(OutputType, InputType, input), the third argument should be " f"an object, rather than a type, but given {input_}.") # If the input_type is not annotated with `@union`, then we validate that the input is # exactly the same type as the input_type. (Why not check unions? We don't have access to # `UnionMembership` to know if it's a valid union member. The engine will check that.) if not union.is_instance( self.input_type) and type(input_) != self.input_type: # We can assume we're using the longhand form because the shorthand form guarantees # that the `input_type` is the same as `input`. raise TypeError( f"Invalid Get. The third argument `{input_}` must have the exact same type as the " f"second argument, {self.input_type}, but had the type {type(input_)}." ) return cast(_Input, input_)
def _register_task(self, tasks, output_type, rule: TaskRule, union_rules: Dict[Type, OrderedSet[Type]]) -> None: """Register the given TaskRule with the native scheduler.""" self._native.lib.tasks_task_begin( tasks, rule.func, output_type, rule.cacheable, rule.canonical_name, rule.desc or "", rule.level.level, ) for selector in rule.input_selectors: self._native.lib.tasks_add_select(tasks, selector) def add_get_edge(product, subject): self._native.lib.tasks_add_get(tasks, product, subject) for the_get in rule.input_gets: if union.is_instance(the_get.subject_declared_type): # If the registered subject type is a union, add Get edges to all registered union members. for union_member in union_rules.get( the_get.subject_declared_type, []): add_get_edge(the_get.product_type, union_member) else: # Otherwise, the Get subject is a "concrete" type, so add a single Get edge. add_get_edge(the_get.product_type, the_get.subject_declared_type) self._native.lib.tasks_task_end(tasks)
def add_type_transition_rule(union_rule): # NB: This does not require that union bases be supplied to `def rules():`, as the union type # is never instantiated! union_base = union_rule.union_base assert union.is_instance(union_base) union_member = union_rule.union_member if union_base not in union_rules: union_rules[union_base] = OrderedSet() union_rules[union_base].add(union_member)
def is_union(self, input_type): """Return whether or not a type is a member of a union.""" # NB: This check is exposed for testing error handling in CFFI methods. This code path should # never be active in normal pants usage. return union.is_instance(input_type)
def extern_is_union(self, context_handle, type_id): """Return whether or not a type is a member of a union.""" c = self._ffi.from_handle(context_handle) input_type = c.from_id(type_id.tup_0) return union.is_instance(input_type)