Example #1
0
  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))
Example #2
0
 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)
Example #3
0
 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)
Example #4
0
    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))