Example #1
0
class EngineChangeCalculator(ChangeCalculator):
    """A ChangeCalculator variant that uses the v2 engine for source mapping."""
    def __init__(self, scheduler, symbol_table, scm):
        """
    :param scheduler: The `Scheduler` instance to use for computing file to target mappings.
    :param symbol_table: The symbol table.
    :param scm: The `Scm` instance to use for change determination.
    """
        super(EngineChangeCalculator, self).__init__(scm or get_scm())
        self._scheduler = scheduler
        self._symbol_table = symbol_table
        self._mapper = EngineSourceMapper(self._scheduler)

    def iter_changed_target_addresses(self, changed_request):
        """Given a `ChangedRequest`, compute and yield all affected target addresses."""
        changed_files = self.changed_files(changed_request.changes_since,
                                           changed_request.diffspec)
        logger.debug('changed files: %s', changed_files)
        if not changed_files:
            return

        changed_addresses = set(
            address
            for address in self._mapper.iter_target_addresses_for_sources(
                changed_files))
        for address in changed_addresses:
            yield address

        if changed_request.include_dependees not in ('direct', 'transitive'):
            return

        # TODO: For dependee finding, we technically only need to parse all build files to collect target
        # dependencies. But in order to fully validate the graph and account for the fact that deleted
        # targets do not show up as changed roots, we use the `TransitiveHydratedTargets` product.
        #   see https://github.com/pantsbuild/pants/issues/382
        specs = (DescendantAddresses(''), )
        adaptor_iter = (t.adaptor
                        for targets in self._scheduler.product_request(
                            TransitiveHydratedTargets, [Specs(specs)])
                        for t in targets.roots)
        graph = _DependentGraph.from_iterable(
            target_types_from_symbol_table(self._symbol_table), adaptor_iter)

        if changed_request.include_dependees == 'direct':
            for address in graph.dependents_of_addresses(changed_addresses):
                yield address
        elif changed_request.include_dependees == 'transitive':
            for address in graph.transitive_dependents_of_addresses(
                    changed_addresses):
                yield address

    def changed_target_addresses(self, changed_request):
        return list(self.iter_changed_target_addresses(changed_request))
class EngineChangeCalculator(ChangeCalculator):
  """A ChangeCalculator variant that uses the v2 engine for source mapping."""

  def __init__(self, scheduler, symbol_table, scm):
    """
    :param scheduler: The `Scheduler` instance to use for computing file to target mappings.
    :param symbol_table: The symbol table.
    :param scm: The `Scm` instance to use for change determination.
    """
    super(EngineChangeCalculator, self).__init__(scm or get_scm())
    self._scheduler = scheduler
    self._symbol_table = symbol_table
    self._mapper = EngineSourceMapper(self._scheduler)

  def iter_changed_target_addresses(self, changed_request):
    """Given a `ChangedRequest`, compute and yield all affected target addresses."""
    changed_files = self.changed_files(changed_request.changes_since, changed_request.diffspec)
    logger.debug('changed files: %s', changed_files)
    if not changed_files:
      return

    changed_addresses = set(address
                            for address
                            in self._mapper.iter_target_addresses_for_sources(changed_files))
    for address in changed_addresses:
      yield address

    if changed_request.include_dependees not in ('direct', 'transitive'):
      return

    # TODO: For dependee finding, we technically only need to parse all build files to collect target
    # dependencies. But in order to fully validate the graph and account for the fact that deleted
    # targets do not show up as changed roots, we use the `TransitiveHydratedTargets` product.
    #   see https://github.com/pantsbuild/pants/issues/382
    specs = (DescendantAddresses(''),)
    adaptor_iter = (t.adaptor
                    for targets in self._scheduler.product_request(TransitiveHydratedTargets,
                                                                   [Specs(specs)])
                    for t in targets.roots)
    graph = _DependentGraph.from_iterable(target_types_from_symbol_table(self._symbol_table),
                                          adaptor_iter)

    if changed_request.include_dependees == 'direct':
      for address in graph.dependents_of_addresses(changed_addresses):
        yield address
    elif changed_request.include_dependees == 'transitive':
      for address in graph.transitive_dependents_of_addresses(changed_addresses):
        yield address

  def changed_target_addresses(self, changed_request):
    return list(self.iter_changed_target_addresses(changed_request))
Example #3
0
class EngineChangeCalculator(ChangeCalculator):
    """A ChangeCalculator variant that uses the v2 engine for source mapping."""
    def __init__(self, scheduler, engine, symbol_table_cls, scm):
        """
    :param Engine engine: The `Engine` instance to use for computing file to target mappings.
    :param Scm engine: The `Scm` instance to use for computing changes.
    """
        super(EngineChangeCalculator, self).__init__(scm)
        self._scheduler = scheduler
        self._engine = engine
        self._symbol_table_cls = symbol_table_cls
        self._mapper = EngineSourceMapper(engine)

    def iter_changed_target_addresses(self, changed_request):
        """Given a `ChangedRequest`, compute and yield all affected target addresses."""
        changed_files = self.changed_files(changed_request.changes_since,
                                           changed_request.diffspec)
        logger.debug('changed files: %s', changed_files)
        if not changed_files:
            return

        changed_addresses = set(
            address
            for address in self._mapper.iter_target_addresses_for_sources(
                changed_files))
        for address in changed_addresses:
            yield address

        if changed_request.include_dependees not in ('direct', 'transitive'):
            return

        # For dependee finding, we need to parse all build files.
        graph = LegacyBuildGraph.create(self._scheduler, self._engine,
                                        self._symbol_table_cls)
        for _ in graph.inject_specs_closure([DescendantAddresses('')]):
            pass

        if changed_request.include_dependees == 'direct':
            emitted = set()
            for address in changed_addresses:
                for dependee in graph.dependents_of(address):
                    if dependee not in emitted:
                        emitted.add(dependee)
                        yield dependee
        elif changed_request.include_dependees == 'transitive':
            for target in graph.transitive_dependees_of_addresses(
                    changed_addresses):
                yield target.address

    def changed_target_addresses(self, changed_request):
        return list(self.iter_changed_target_addresses(changed_request))
Example #4
0
class EngineChangeCalculator(ChangeCalculator):
    """A ChangeCalculator variant that uses the v2 engine for source mapping."""
    def __init__(self, scheduler, symbol_table, scm):
        """
    :param scheduler: The `Scheduler` instance to use for computing file to target mappings.
    :param symbol_table: The symbol table.
    :param scm: The `Scm` instance to use for change determination.
    """
        super(EngineChangeCalculator, self).__init__(scm or get_scm())
        self._scheduler = scheduler
        self._symbol_table = symbol_table
        self._mapper = EngineSourceMapper(self._scheduler)

    def iter_changed_target_addresses(self, changed_request):
        """Given a `ChangedRequest`, compute and yield all affected target addresses."""
        changed_files = self.changed_files(changed_request.changes_since,
                                           changed_request.diffspec)
        logger.debug('changed files: %s', changed_files)
        if not changed_files:
            return

        changed_addresses = set(
            address
            for address in self._mapper.iter_target_addresses_for_sources(
                changed_files))
        for address in changed_addresses:
            yield address

        if changed_request.include_dependees not in ('direct', 'transitive'):
            return

        # For dependee finding, we need to parse all build files to collect all structs. But we
        # don't need to fully hydrate targets (ie, expand their source globs), and so we use
        # the `HydratedStructs` product. See #4535 for more info.
        adaptor_iter = (t for targets in self._scheduler.product_request(
            HydratedStructs, [DescendantAddresses('')])
                        for t in targets.dependencies)
        graph = _DependentGraph.from_iterable(
            target_types_from_symbol_table(self._symbol_table), adaptor_iter)

        if changed_request.include_dependees == 'direct':
            for address in graph.dependents_of_addresses(changed_addresses):
                yield address
        elif changed_request.include_dependees == 'transitive':
            for address in graph.transitive_dependents_of_addresses(
                    changed_addresses):
                yield address

    def changed_target_addresses(self, changed_request):
        return list(self.iter_changed_target_addresses(changed_request))
Example #5
0
class EngineChangeCalculator(ChangeCalculator):
  """A ChangeCalculator variant that uses the v2 engine for source mapping."""

  def __init__(self, scheduler, engine, symbol_table_cls, scm):
    """
    :param Engine engine: The `Engine` instance to use for computing file to target mappings.
    :param Scm engine: The `Scm` instance to use for computing changes.
    """
    super(EngineChangeCalculator, self).__init__(scm)
    self._scheduler = scheduler
    self._engine = engine
    self._symbol_table_cls = symbol_table_cls
    self._mapper = EngineSourceMapper(engine)

  def iter_changed_target_addresses(self, changed_request):
    """Given a `ChangedRequest`, compute and yield all affected target addresses."""
    changed_files = self.changed_files(changed_request.changes_since, changed_request.diffspec)
    logger.debug('changed files: %s', changed_files)
    if not changed_files:
      return

    changed_addresses = set(address
                            for address
                            in self._mapper.iter_target_addresses_for_sources(changed_files))
    for address in changed_addresses:
      yield address

    if changed_request.include_dependees not in ('direct', 'transitive'):
      return

    # For dependee finding, we need to parse all build files.
    graph = LegacyBuildGraph.create(self._scheduler, self._engine, self._symbol_table_cls)
    for _ in graph.inject_specs_closure([DescendantAddresses('')]):
      pass

    if changed_request.include_dependees == 'direct':
      emitted = set()
      for address in changed_addresses:
        for dependee in graph.dependents_of(address):
          if dependee not in emitted:
            emitted.add(dependee)
            yield dependee
    elif changed_request.include_dependees == 'transitive':
      for target in graph.transitive_dependees_of_addresses(changed_addresses):
        yield target.address

  def changed_target_addresses(self, changed_request):
    return list(self.iter_changed_target_addresses(changed_request))
Example #6
0
class EngineChangeCalculator(ChangeCalculator):
    """A ChangeCalculator variant that uses the v2 engine for source mapping."""
    def __init__(self, scheduler, symbol_table, scm):
        """
    :param Engine engine: The `Engine` instance to use for computing file to target mappings.
    :param Scm engine: The `Scm` instance to use for computing changes.
    """
        super(EngineChangeCalculator, self).__init__(scm)
        self._scheduler = scheduler
        self._symbol_table = symbol_table
        self._mapper = EngineSourceMapper(self._scheduler)

    def iter_changed_target_addresses(self, changed_request):
        """Given a `ChangedRequest`, compute and yield all affected target addresses."""
        changed_files = self.changed_files(changed_request.changes_since,
                                           changed_request.diffspec)
        logger.debug('changed files: %s', changed_files)
        if not changed_files:
            return

        changed_addresses = set(
            address
            for address in self._mapper.iter_target_addresses_for_sources(
                changed_files))
        for address in changed_addresses:
            yield address

        if changed_request.include_dependees not in ('direct', 'transitive'):
            return

        # For dependee finding, we need to parse all build files.
        product_iter = (t for targets in self._scheduler.product_request(
            HydratedTargets, [DescendantAddresses('')])
                        for t in targets.dependencies)
        graph = _HydratedTargetDependentGraph.from_iterable(
            target_types_from_symbol_table(self._symbol_table), product_iter)

        if changed_request.include_dependees == 'direct':
            for address in graph.dependents_of_addresses(changed_addresses):
                yield address
        elif changed_request.include_dependees == 'transitive':
            for address in graph.transitive_dependents_of_addresses(
                    changed_addresses):
                yield address

    def changed_target_addresses(self, changed_request):
        return list(self.iter_changed_target_addresses(changed_request))
Example #7
0
class EngineChangeCalculator(ChangeCalculator):
  """A ChangeCalculator variant that uses the v2 engine for source mapping."""

  def __init__(self, scheduler, symbol_table, scm):
    """
    :param Engine engine: The `Engine` instance to use for computing file to target mappings.
    :param Scm engine: The `Scm` instance to use for computing changes.
    """
    super(EngineChangeCalculator, self).__init__(scm)
    self._scheduler = scheduler
    self._symbol_table = symbol_table
    self._mapper = EngineSourceMapper(self._scheduler)

  def iter_changed_target_addresses(self, changed_request):
    """Given a `ChangedRequest`, compute and yield all affected target addresses."""
    changed_files = self.changed_files(changed_request.changes_since, changed_request.diffspec)
    logger.debug('changed files: %s', changed_files)
    if not changed_files:
      return

    changed_addresses = set(address
                            for address
                            in self._mapper.iter_target_addresses_for_sources(changed_files))
    for address in changed_addresses:
      yield address

    if changed_request.include_dependees not in ('direct', 'transitive'):
      return

    # For dependee finding, we need to parse all build files.
    product_iter = (t
                    for targets in self._scheduler.product_request(HydratedTargets, [DescendantAddresses('')])
                    for t in targets.dependencies)
    graph = _HydratedTargetDependentGraph.from_iterable(target_types_from_symbol_table(self._symbol_table),
                                                        product_iter)

    if changed_request.include_dependees == 'direct':
      for address in graph.dependents_of_addresses(changed_addresses):
        yield address
    elif changed_request.include_dependees == 'transitive':
      for address in graph.transitive_dependents_of_addresses(changed_addresses):
        yield address

  def changed_target_addresses(self, changed_request):
    return list(self.iter_changed_target_addresses(changed_request))
Example #8
0
class OwnerCalculator(object):
    """An OwnerCalculator that finds the target addresses of the files passed down as arguments
  to --owner-of
  """
    def __init__(self, scheduler, symbol_table):
        """
    :param scheduler: The `Scheduler` instance to use for computing file to target mapping
    :param symbol_table: The symbol table.
    """
        self._scheduler = scheduler
        self._symbol_table = symbol_table
        self._mapper = EngineSourceMapper(self._scheduler)

    def iter_owner_target_addresses(self, owned_files):
        """Given an list of owned files, compute and yield all affected target addresses"""
        owner_addresses = set(
            address
            for address in self._mapper.iter_target_addresses_for_sources(
                owned_files))
        for address in owner_addresses:
            yield address

    def owner_target_addresses(self, owner_request):
        return list(self.iter_owner_target_addresses(owner_request))
class OwnerCalculator(object):
  """An OwnerCalculator that finds the target addresses of the files passed down as arguments
  to --owner-of
  """

  def __init__(self, scheduler, symbol_table):
    """
    :param scheduler: The `Scheduler` instance to use for computing file to target mapping
    :param symbol_table: The symbol table.
    """
    self._scheduler = scheduler
    self._symbol_table = symbol_table
    self._mapper = EngineSourceMapper(self._scheduler)

  def iter_owner_target_addresses(self, owned_files):
    """Given an list of owned files, compute and yield all affected target addresses"""
    owner_addresses = set(address
                          for address
                          in self._mapper.iter_target_addresses_for_sources(owned_files))
    for address in owner_addresses:
      yield address

  def owner_target_addresses(self, owner_request):
    return list(self.iter_owner_target_addresses(owner_request))