def step(self, dependency_states, step_context): # Request default Variants for the subject, so that if there are any we can propagate # them to task nodes. variants = self.variants variants_node = self._variants_node() if variants_node: dep_state = dependency_states.get(variants_node, None) if dep_state is None or type(dep_state) == Waiting: return Waiting([variants_node]) elif type(dep_state) == Return: # A subject's variants are overridden by any dependent's requested variants, so # we merge them left to right here. variants = Variants.merge(dep_state.value.default.items(), variants) # If there is a variant_key, see whether it has been configured. variant_value = None if self.variant_key: variant_values = [value for key, value in variants if key == self.variant_key] if variants else None if not variant_values: # Select cannot be satisfied: no variant configured for this key. return Noop('Variant key {} was not configured in variants {}'.format( self.variant_key, variants)) variant_value = variant_values[0] # If the Subject "is a" or "has a" Product, then we're done. literal_value = self._select_literal(self.subject, variant_value) if literal_value is not None: return Return(literal_value) # Else, attempt to use a configured task to compute the value. has_waiting_dep = False dependencies = list(step_context.gen_nodes(self.subject, self.product, variants)) matches = {} for dep in dependencies: dep_state = dependency_states.get(dep, None) if dep_state is None or type(dep_state) == Waiting: has_waiting_dep = True continue elif type(dep_state) == Throw: return dep_state elif type(dep_state) == Noop: continue elif type(dep_state) != Return: State.raise_unrecognized(dep_state) # We computed a value: see whether we can use it. literal_value = self._select_literal(dep_state.value, variant_value) if literal_value is not None: matches[dep] = literal_value if has_waiting_dep: return Waiting(dependencies) elif len(matches) > 1: # TODO: Multiple successful tasks are not currently supported. We should allow for this # by adding support for "mergeable" products. see: # https://github.com/pantsbuild/pants/issues/2526 return Throw(ConflictingProducersError.create(self.subject, self.product, matches)) elif len(matches) == 1: return Return(matches.values()[0]) return Noop('No source of {}.'.format(self))
def _dependency_nodes(self, step_context, dep_product): for dependency in getattr(dep_product, self.field or 'dependencies'): variants = self.variants if isinstance(dependency, Address): # If a subject has literal variants for particular dependencies, they win over all else. dependency, literal_variants = parse_variants(dependency) variants = Variants.merge(variants, literal_variants) yield SelectNode(dependency, self.product, variants, None)
def step(self, dependency_states, step_context): # Request default Variants for the subject, so that if there are any we can propagate # them to task nodes. variants = self.variants variants_node = self._variants_node() if variants_node: dep_state = dependency_states.get(variants_node, None) if dep_state is None or type(dep_state) == Waiting: return Waiting([variants_node]) elif type(dep_state) == Return: # A subject's variants are overridden by any dependent's requested variants, so # we merge them left to right here. variants = Variants.merge(dep_state.value.default.items(), variants) # If there is a variant_key, see whether it has been configured. variant_value = None if self.variant_key: variant_values = [ value for key, value in variants if key == self.variant_key ] if variants else None if not variant_values: # Select cannot be satisfied: no variant configured for this key. return Noop( 'Variant key {} was not configured in variants {}'.format( self.variant_key, variants)) variant_value = variant_values[0] # If the Subject "is a" or "has a" Product, then we're done. literal_value = self._select_literal(self.subject, variant_value) if literal_value is not None: return Return(literal_value) # Else, attempt to use a configured task to compute the value. has_waiting_dep = False dependencies = list( step_context.gen_nodes(self.subject, self.product, variants)) matches = {} for dep in dependencies: dep_state = dependency_states.get(dep, None) if dep_state is None or type(dep_state) == Waiting: has_waiting_dep = True continue elif type(dep_state) == Throw: return dep_state elif type(dep_state) == Noop: continue elif type(dep_state) != Return: State.raise_unrecognized(dep_state) # We computed a value: see whether we can use it. literal_value = self._select_literal(dep_state.value, variant_value) if literal_value is not None: matches[dep] = literal_value if has_waiting_dep: return Waiting(dependencies) elif len(matches) > 1: # TODO: Multiple successful tasks are not currently supported. We should allow for this # by adding support for "mergeable" products. see: # https://github.com/pantsbuild/pants/issues/2526 return Throw( ConflictingProducersError.create(self.subject, self.product, matches)) elif len(matches) == 1: return Return(matches.values()[0]) return Noop('No source of {}.'.format(self))