示例#1
0
        async def single_build_file_address(
            build_file_addresses: BuildFileAddresses, ) -> BuildFileAddress:
            if len(build_file_addresses.dependencies) == 0:
                raise ResolveError("No targets were matched")
            if len(build_file_addresses.dependencies) > 1:
                targets = [bfa.to_address() for bfa in build_file_addresses]
                output = '\n '.join(str(target) for target in targets)

                raise ResolveError(
                    "Expected a single target, but was given multiple targets:\n"
                    f"Did you mean one of:\n {output}")
            return build_file_addresses.dependencies[0]
示例#2
0
        def single_build_file_address(specs: Specs) -> BuildFileAddress:
            build_file_addresses = yield Get(BuildFileAddresses, Specs, specs)
            if len(build_file_addresses.dependencies) == 0:
                raise ResolveError("No targets were matched")
            if len(build_file_addresses.dependencies) > 1:
                potential_addresses = yield Get(BuildFileAddresses, Specs,
                                                specs)
                targets = [bfa.to_address() for bfa in potential_addresses]
                output = '\n '.join(str(target) for target in targets)

                raise ResolveError(
                    "Expected a single target, but was given multiple targets:\n"
                    f"Did you mean one of:\n {output}")
            yield build_file_addresses.dependencies[0]
示例#3
0
def _raise_did_you_mean(address_family, name):
    names = [a.target_name for a in address_family.addressables]
    possibilities = '\n  '.join(':{}'.format(target_name)
                                for target_name in sorted(names))
    raise ResolveError('"{}" was not found in namespace "{}". '
                       'Did you mean one of:\n  {}'.format(
                           name, address_family.namespace, possibilities))
示例#4
0
def addresses_from_address_families(address_mapper, address_families, spec):
  """Given a list of AddressFamilies and a Spec, return matching Addresses.

  Raises a ResolveError if:
     - there were no matching AddressFamilies, or
     - the Spec matches no addresses for SingleAddresses.
  """
  if not address_families:
    raise ResolveError('Path "{}" contains no BUILD files.'.format(spec.directory))

  def exclude_address(address):
    if address_mapper.exclude_patterns:
      address_str = address.spec
      return any(p.search(address_str) is not None for p in address_mapper.exclude_patterns)
    return False

  if type(spec) in (DescendantAddresses, SiblingAddresses, AscendantAddresses):
    addresses = tuple(a
                      for af in address_families
                      for a in af.addressables.keys()
                      if not exclude_address(a))
  elif type(spec) is SingleAddress:
    # TODO Could assert len(address_families) == 1, as it should always be true in this case.
    addresses = tuple(a
                      for af in address_families
                      for a in af.addressables.keys()
                      if a.target_name == spec.name and not exclude_address(a))
    if not addresses:
      if len(address_families) == 1:
        _raise_did_you_mean(address_families[0], spec.name)
  else:
    raise ValueError('Unrecognized Spec type: {}'.format(spec))

  return BuildFileAddresses(addresses)
示例#5
0
async def addresses_with_origins_from_filesystem_specs(
    filesystem_specs: FilesystemSpecs,
    global_options: GlobalOptions,
) -> AddressesWithOrigins:
    """Find the owner(s) for each FilesystemSpec while preserving the original FilesystemSpec those
  owners come from.
  """
    pathglobs_per_include = (filesystem_specs.path_globs_for_spec(spec)
                             for spec in filesystem_specs.includes)
    snapshot_per_include = await MultiGet(Get[Snapshot](PathGlobs, pg)
                                          for pg in pathglobs_per_include)
    owners_per_include = await MultiGet(
        Get[Owners](OwnersRequest(sources=snapshot.files))
        for snapshot in snapshot_per_include)
    result: List[AddressWithOrigin] = []
    for spec, owners in zip(filesystem_specs.includes, owners_per_include):
        if (global_options.owners_not_found_behavior !=
                OwnersNotFoundBehavior.ignore
                and isinstance(spec, FilesystemLiteralSpec)
                and not owners.addresses):
            file_path = PurePath(spec.to_spec_string())
            msg = (
                f"No owning targets could be found for the file `{file_path}`.\n\nPlease check "
                f"that there is a BUILD file in `{file_path.parent}` with a target whose `sources` field "
                f"includes `{file_path}`. See https://www.pantsbuild.org/build_files.html."
            )
            if global_options.owners_not_found_behavior == OwnersNotFoundBehavior.warn:
                logger.warning(msg)
            else:
                raise ResolveError(msg)
        result.extend(
            AddressWithOrigin(address=bfa, origin=spec)
            for bfa in owners.addresses)
    return AddressesWithOrigins(result)
示例#6
0
async def parse_address_family(address_mapper: AddressMapper, directory: Dir) -> AddressFamily:
  """Given an AddressMapper and a directory, return an AddressFamily.

  The AddressFamily may be empty, but it will not be None.
  """
  path_globs = PathGlobs(
    globs=(
      *(os.path.join(directory.path, p) for p in address_mapper.build_patterns),
      *(f"!{p}" for p in address_mapper.build_ignore_patterns),
    )
  )
  snapshot = await Get[Snapshot](PathGlobs, path_globs)
  files_content = await Get[FilesContent](Digest, snapshot.directory_digest)

  if not files_content:
    raise ResolveError(
      'Directory "{}" does not contain any BUILD files.'.format(directory.path)
    )
  address_maps = []
  for filecontent_product in files_content:
    address_maps.append(
      AddressMap.parse(
        filecontent_product.path, filecontent_product.content, address_mapper.parser
      )
    )
  return AddressFamily.create(directory.path, address_maps)
示例#7
0
def parse_address_family(address_mapper, directory):
    """Given an AddressMapper and a directory, return an AddressFamily.

  The AddressFamily may be empty, but it will not be None.
  """
    patterns = tuple(
        join(directory.path, p) for p in address_mapper.build_patterns)
    path_globs = PathGlobs.create('',
                                  include=patterns,
                                  exclude=address_mapper.build_ignore_patterns)
    snapshot = yield Get(Snapshot, PathGlobs, path_globs)
    files_content = yield Get(FilesContent, DirectoryDigest,
                              snapshot.directory_digest)

    if not files_content:
        raise ResolveError(
            'Directory "{}" does not contain build files.'.format(
                directory.path))
    address_maps = []
    for filecontent_product in files_content.dependencies:
        address_maps.append(
            AddressMap.parse(filecontent_product.path,
                             filecontent_product.content,
                             address_mapper.parser))
    yield AddressFamily.create(directory.path, address_maps)
示例#8
0
async def provenanced_addresses_from_address_families(
    address_mapper: AddressMapper,
    address_specs: AddressSpecs,
) -> ProvenancedBuildFileAddresses:
    """Given an AddressMapper and list of AddressSpecs, return matching ProvenancedBuildFileAddresses.

  :raises: :class:`ResolveError` if:
     - there were no matching AddressFamilies, or
     - the AddressSpec matches no addresses for SingleAddresses.
  :raises: :class:`AddressLookupError` if no targets are matched for non-SingleAddress specs.
  """
    # Capture a Snapshot covering all paths for these AddressSpecs, then group by directory.
    snapshot = await Get[Snapshot](PathGlobs,
                                   _address_spec_to_globs(
                                       address_mapper, address_specs))
    dirnames = {dirname(f) for f in snapshot.files}
    address_families = await MultiGet(Get[AddressFamily](Dir(d))
                                      for d in dirnames)
    address_family_by_directory = {af.namespace: af for af in address_families}

    matched_addresses = OrderedSet()
    addr_to_provenance: Dict[BuildFileAddress, AddressSpec] = {}

    for address_spec in address_specs:
        # NB: if an address spec is provided which expands to some number of targets, but those targets
        # match --exclude-target-regexp, we do NOT fail! This is why we wait to apply the tag and
        # exclude patterns until we gather all the targets the address spec would have matched
        # without them.
        try:
            addr_families_for_spec = address_spec.matching_address_families(
                address_family_by_directory)
        except AddressSpec.AddressFamilyResolutionError as e:
            raise ResolveError(e) from e

        try:
            all_addr_tgt_pairs = address_spec.address_target_pairs_from_address_families(
                addr_families_for_spec)
            for addr, _ in all_addr_tgt_pairs:
                # A target might be covered by multiple specs, so we take the most specific one.
                addr_to_provenance[addr] = more_specific(
                    addr_to_provenance.get(addr), address_spec)
        except AddressSpec.AddressResolutionError as e:
            raise AddressLookupError(e) from e
        except SingleAddress._SingleAddressResolutionError as e:
            _raise_did_you_mean(e.single_address_family, e.name, source=e)

        matched_addresses.update(
            addr for (addr, tgt) in all_addr_tgt_pairs
            if address_specs.matcher.matches_target_address_pair(addr, tgt))

    # NB: This may be empty, as the result of filtering by tag and exclude patterns!
    return ProvenancedBuildFileAddresses(
        tuple(
            ProvenancedBuildFileAddress(build_file_address=addr,
                                        provenance=addr_to_provenance[addr])
            for addr in matched_addresses))
示例#9
0
def _raise_did_you_mean(address_family: AddressFamily, name: str, source=None) -> None:
  names = [a.target_name for a in address_family.addressables]
  possibilities = "\n  ".join(":{}".format(target_name) for target_name in sorted(names))

  resolve_error = ResolveError(
    '"{}" was not found in namespace "{}". '
    "Did you mean one of:\n  {}".format(name, address_family.namespace, possibilities)
  )

  if source:
    raise resolve_error from source
  raise resolve_error
示例#10
0
def parse_address_family(address_mapper, path, build_files):
  """Given the contents of the build files in one directory, return an AddressFamily.

  The AddressFamily may be empty, but it will not be None.
  """
  files_content = build_files.files_content.dependencies
  if not files_content:
    raise ResolveError('Directory "{}" does not contain build files.'.format(path))
  address_maps = []
  for filecontent_product in files_content:
    address_maps.append(AddressMap.parse(filecontent_product.path,
                                         filecontent_product.content,
                                         address_mapper.parser))
  return AddressFamily.create(path.path, address_maps)
示例#11
0
文件: graph.py 项目: ebubae/pants
def parse_address_family(address_mapper, path, build_files_content):
    """Given the contents of the build files in one directory, return an AddressFamily.

  The AddressFamily may be empty, but it will not be None.
  """
    if not build_files_content.dependencies:
        raise ResolveError(
            'Directory "{}" does not contain build files.'.format(path))
    address_maps = []
    for filepath, filecontent in build_files_content.dependencies:
        address_maps.append(
            AddressMap.parse(filepath, filecontent,
                             address_mapper.symbol_table_cls,
                             address_mapper.parser_cls))
    return AddressFamily.create(path.path, address_maps)
示例#12
0
文件: graph.py 项目: ebubae/pants
def filter_buildfile_paths(address_mapper, directory_listing):
    if not directory_listing.exists:
        raise ResolveError('Directory "{}" does not exist.'.format(
            directory_listing.directory.path))

    build_pattern = address_mapper.build_pattern

    def match(stat):
        return type(stat) is File and fnmatch(basename(stat.path),
                                              build_pattern)

    build_files = tuple(
        Path(stat.path, stat) for stat in directory_listing.dependencies
        if match(stat))
    return BuildFiles(build_files)
示例#13
0
def filter_buildfile_paths(address_mapper, directory_listing):
    if not directory_listing.exists:
        raise ResolveError('Directory "{}" does not exist.'.format(
            directory_listing.directory.path))

    def match(stat):
        # Short circuit for ignored paths.
        if address_mapper.build_ignore_patterns.match_file(stat.path):
            return False

        return (type(stat) is File and any(
            fnmatch(basename(stat.path), pattern)
            for pattern in address_mapper.build_patterns))

    build_files = tuple(
        Path(stat.path, stat) for stat in directory_listing.dependencies
        if match(stat))
    return BuildFiles(build_files)
示例#14
0
def filter_buildfile_paths(address_mapper, directory_listing):
    if not directory_listing.exists:
        raise ResolveError('Directory "{}" does not exist.'.format(
            directory_listing.directory.path))

    build_pattern = address_mapper.build_pattern

    def match(stat):
        # TODO: Use match_file instead when pathspec 0.4.1 (TBD) is released.
        ignored = any(
            True for _ in address_mapper.build_ignore_patterns.match_files(
                [stat.path]))
        return (not ignored) and type(stat) is File and fnmatch(
            basename(stat.path), build_pattern)

    build_files = tuple(
        Path(stat.path, stat) for stat in directory_listing.dependencies
        if match(stat))
    return BuildFiles(build_files)
示例#15
0
def parse_address_family(address_mapper, path, build_files):
  """Given the contents of the build files in one directory, return an AddressFamily.

  The AddressFamily may be empty, but it will not be None.
  """
  files_content = build_files.files_content.dependencies
  if not files_content:
    raise ResolveError('Directory "{}" does not contain build files.'.format(path))
  address_maps = []
  paths = (f.path for f in files_content)
  ignored_paths = set(address_mapper.build_ignore_patterns.match_files(paths))
  for filecontent_product in files_content:
    if filecontent_product.path in ignored_paths:
      continue
    address_maps.append(AddressMap.parse(filecontent_product.path,
                                         filecontent_product.content,
                                         address_mapper.symbol_table_cls,
                                         address_mapper.parser_cls,
                                         address_mapper.exclude_patterns))
  return AddressFamily.create(path.path, address_maps)
示例#16
0
def addresses_from_address_families(address_mapper: AddressMapper,
                                    specs: Specs) -> BuildFileAddresses:
    """Given an AddressMapper and list of Specs, return matching BuildFileAddresses.

  :raises: :class:`ResolveError` if:
     - there were no matching AddressFamilies, or
     - the Spec matches no addresses for SingleAddresses.
  :raises: :class:`AddressLookupError` if no targets are matched for non-SingleAddress specs.
  """
    # Capture a Snapshot covering all paths for these Specs, then group by directory.
    snapshot = yield Get(Snapshot, PathGlobs,
                         _spec_to_globs(address_mapper, specs))
    dirnames = {dirname(f) for f in snapshot.files}
    address_families = yield [Get(AddressFamily, Dir(d)) for d in dirnames]
    address_family_by_directory = {af.namespace: af for af in address_families}

    matched_addresses = OrderedSet()
    for spec in specs:
        # NB: if a spec is provided which expands to some number of targets, but those targets match
        # --exclude-target-regexp, we do NOT fail! This is why we wait to apply the tag and exclude
        # patterns until we gather all the targets the spec would have matched without them.
        try:
            addr_families_for_spec = spec.matching_address_families(
                address_family_by_directory)
        except Spec.AddressFamilyResolutionError as e:
            raise ResolveError(e) from e

        try:
            all_addr_tgt_pairs = spec.address_target_pairs_from_address_families(
                addr_families_for_spec)
        except Spec.AddressResolutionError as e:
            raise AddressLookupError(e) from e
        except SingleAddress._SingleAddressResolutionError as e:
            _raise_did_you_mean(e.single_address_family, e.name, source=e)

        matched_addresses.update(
            addr for (addr, tgt) in all_addr_tgt_pairs
            if specs.matcher.matches_target_address_pair(addr, tgt))

    # NB: This may be empty, as the result of filtering by tag and exclude patterns!
    yield BuildFileAddresses(tuple(matched_addresses))
示例#17
0
文件: graph.py 项目: neven7/pants
def _raise_did_you_mean(address_family, name):
    possibilities = '\n  '.join(str(a) for a in address_family.addressables)
    raise ResolveError('A Struct was not found in namespace {} for name "{}". '
                       'Did you mean one of?:\n  {}'.format(
                           address_family.namespace, name, possibilities))
示例#18
0
 def raise_if_empty_address_families():
   if not address_families:
     raise ResolveError('Path "{}" contains no BUILD files.'.format(spec.directory))
示例#19
0
 def raise_empty_address_family(spec):
     raise ResolveError('Path "{}" contains no BUILD files.'.format(
         spec.directory))