コード例 #1
0
    def initialize_parse_state(self, build_file):
        """Creates a fresh parse state for the given build file."""
        type_aliases = self._exposed_objects.copy()

        registered_addressable_instances = []

        def registration_callback(address, addressable):
            registered_addressable_instances.append((address, addressable))

        for alias, addressable_type in self._addressable_alias_map.items():
            call_proxy = AddressableCallProxy(
                addressable_type=addressable_type,
                build_file=build_file,
                registration_callback=registration_callback)
            type_aliases[alias] = call_proxy

        parse_context = ParseContext(rel_path=build_file.spec_path,
                                     type_aliases=type_aliases)

        parse_globals = type_aliases.copy()
        for alias, object_factory in self._exposed_context_aware_object_factories.items(
        ):
            parse_globals[alias] = object_factory(parse_context)

        return self.ParseState(registered_addressable_instances, parse_globals)
コード例 #2
0
ファイル: build_configuration.py プロジェクト: rkstap/pants
    def initialize_parse_state(self, build_file):
        """Creates a fresh parse state for the given build file.

    :param build_file: The BUILD file to set up a new ParseState for.
    :type build_file: :class:`pants.base.build_file.BuildFile`
    :returns: A fresh ParseState for parsing the given `build_file` with.
    :rtype: :class:`BuildConfiguration.ParseState`
    """
        # TODO(John Sirois): Introduce a factory method to seal the BuildConfiguration and add a check
        # there that all anonymous types are covered by context aware object factories that are
        # Macro instances.  Without this, we could have non-Macro context aware object factories being
        # asked to be a BuildFileTargetFactory when they are not (in SourceRoot registration context).
        # See: https://github.com/pantsbuild/pants/issues/2125
        type_aliases = self._exposed_object_by_alias.copy()
        parse_context = ParseContext(rel_path=build_file.spec_path,
                                     type_aliases=type_aliases)

        def create_call_proxy(tgt_type, tgt_alias=None):
            def registration_callback(address, addressable):
                parse_context._storage.add(addressable,
                                           name=address.target_name)

            addressable_factory = self._get_addressable_factory(
                tgt_type, tgt_alias)
            return AddressableCallProxy(
                addressable_factory=addressable_factory,
                build_file=build_file,
                registration_callback=registration_callback)

        # Expose all aliased Target types.
        for alias, target_type in self._target_by_alias.items():
            proxy = create_call_proxy(target_type, alias)
            type_aliases[alias] = proxy

        # Expose aliases for exposed objects and targets in the BUILD file.
        parse_globals = type_aliases.copy()

        # Now its safe to add mappings from both the directly exposed and macro-created target types to
        # their call proxies for context awares and macros to use to manufacture targets by type
        # instead of by alias.
        for alias, target_type in self._target_by_alias.items():
            proxy = type_aliases[alias]
            type_aliases[target_type] = proxy

        for target_macro_factory in self._target_macro_factory_by_alias.values(
        ):
            for target_type in target_macro_factory.target_types:
                proxy = create_call_proxy(target_type)
                type_aliases[target_type] = proxy

        for alias, object_factory in self._exposed_context_aware_object_factory_by_alias.items(
        ):
            parse_globals[alias] = object_factory(parse_context)

        for alias, target_macro_factory in self._target_macro_factory_by_alias.items(
        ):
            parse_globals[alias] = target_macro_factory.target_macro(
                parse_context)

        return self.ParseState(parse_context, parse_globals)
コード例 #3
0
    def __init__(self, address=None, payload=None, sources=None, **kwargs):
        if not sources:
            # We grab all files in the current directory except BUILD files for 2 reasons:
            # 1. cgo: If a file imports "C" then it may rely on sibling .c, .cc, etc files that `go build`
            #    will compile.
            # 2. resources: Even though go does not support them; ie by providing a protocol to embed them
            #    in binaries, it does allow them to be placed in a directory where a test might use them
            #    for example via plain old filesystem access.
            globs = Globs(
                ParseContext(rel_path=address.spec_path, type_aliases={}))
            sources = globs(
                '*',
                exclude=[
                    globs('BUILD*'),
                    # This skips subdir content.
                    globs('*/**')
                ])

        payload = payload or Payload()
        payload.add_fields({
            'sources':
            self.create_sources_field(sources=sources,
                                      sources_rel_path=address.spec_path,
                                      key_arg='sources'),
        })
        super(GoLocalSource, self).__init__(address=address,
                                            payload=payload,
                                            **kwargs)
コード例 #4
0
    def _get_symbols(cls, symbol_table_cls):
        symbol_table = symbol_table_cls.table()
        # TODO: nasty escape hatch
        aliases = symbol_table_cls.aliases()

        class Registrar(BuildFileTargetFactory):
            def __init__(self, type_alias, object_type):
                self._type_alias = type_alias
                self._object_type = object_type
                self._serializable = Serializable.is_serializable_type(
                    self._object_type)

            @memoized_property
            def target_types(self):
                return [self._object_type]

            def __call__(self, *args, **kwargs):
                name = kwargs.get('name')
                if name and self._serializable:
                    obj = self._object_type(type_alias=self._type_alias,
                                            **kwargs)
                    cls._objects.append(obj)
                    return obj
                else:
                    return self._object_type(*args, **kwargs)

        # Compute a single ParseContext for a default path, which we will mutate for each parsed path.
        symbols = {}
        for alias, target_macro_factory in aliases.target_macro_factories.items(
        ):
            for target_type in target_macro_factory.target_types:
                symbols[target_type] = TargetAdaptor
        parse_context = ParseContext(rel_path='', type_aliases=symbols)

        for alias, symbol in symbol_table.items():
            registrar = Registrar(alias, symbol)
            symbols[alias] = registrar
            symbols[symbol] = registrar

        if aliases.objects:
            symbols.update(aliases.objects)

        # Compute "per path" symbols (which will all use the same mutable ParseContext).
        aliases = symbol_table_cls.aliases()
        for alias, object_factory in aliases.context_aware_object_factories.items(
        ):
            symbols[alias] = object_factory(parse_context)

        for alias, target_macro_factory in aliases.target_macro_factories.items(
        ):
            symbols[alias] = target_macro_factory.target_macro(parse_context)
            for target_type in target_macro_factory.target_types:
                symbols[target_type] = TargetAdaptor

        # TODO: Replace builtins for paths with objects that will create wrapped PathGlobs objects.
        symbols['globs'] = Globs
        symbols['rglobs'] = RGlobs
        symbols['zglobs'] = ZGlobs

        return symbols, parse_context
コード例 #5
0
ファイル: commands.py プロジェクト: simudream/pants
    def per_path_symbol_factory(path, global_symbols):
        per_path_symbols = {}

        symbols = global_symbols.copy()
        for alias, target_macro_factory in aliases.target_macro_factories.items(
        ):
            for target_type in target_macro_factory.target_types:
                symbols[
                    target_type] = lambda *args, **kwargs: per_path_symbols[
                        alias](*args, **kwargs)

        parse_context = ParseContext(rel_path=os.path.relpath(
            os.path.dirname(path), build_root),
                                     type_aliases=symbols)

        for alias, object_factory in aliases.context_aware_object_factories.items(
        ):
            per_path_symbols[alias] = object_factory(parse_context)

        for alias, target_macro_factory in aliases.target_macro_factories.items(
        ):
            target_macro = target_macro_factory.target_macro(parse_context)
            per_path_symbols[alias] = target_macro
            for target_type in target_macro_factory.target_types:
                per_path_symbols[target_type] = target_macro

        return per_path_symbols
コード例 #6
0
    def initialize_parse_state(self, build_file):
        """Creates a fresh parse state for the given build file."""
        type_aliases = self._exposed_objects.copy()

        registered_addressable_instances = []

        def registration_callback(address, addressable):
            registered_addressable_instances.append((address, addressable))

        for alias, addressable_type in self._addressable_alias_map.items():
            call_proxy = AddressableCallProxy(
                addressable_type=addressable_type,
                build_file=build_file,
                registration_callback=registration_callback)
            type_aliases[alias] = call_proxy

        # Expose aliases for exposed objects and addressables in the BUILD file.
        parse_globals = type_aliases.copy()

        # Now its safe to add concrete addressable type to proxy mappings for context awares to use.
        for alias, addressable_type in self._addressable_alias_map.items():
            target_type = addressable_type.get_target_type()
            proxy = type_aliases[alias]
            type_aliases[target_type] = proxy

        parse_context = ParseContext(rel_path=build_file.spec_path,
                                     type_aliases=type_aliases)

        for alias, object_factory in self._exposed_context_aware_object_factories.items(
        ):
            parse_globals[alias] = object_factory(parse_context)

        return self.ParseState(registered_addressable_instances, parse_globals)
コード例 #7
0
ファイル: parser.py プロジェクト: neven7/pants
  def _get_symbols(cls, symbol_table_cls):
    symbol_table = symbol_table_cls.table()
    # TODO: Nasty escape hatch: see https://github.com/pantsbuild/pants/issues/3561
    aliases = symbol_table_cls.aliases()

    class Registrar(BuildFileTargetFactory):
      def __init__(self, type_alias, object_type):
        self._type_alias = type_alias
        self._object_type = object_type
        self._serializable = Serializable.is_serializable_type(self._object_type)

      @memoized_property
      def target_types(self):
        return [self._object_type]

      def __call__(self, *args, **kwargs):
        name = kwargs.get('name')
        if name and self._serializable:
          kwargs['type_alias'] = self._type_alias
          obj = self._object_type(**kwargs)
          cls._objects.append(obj)
          return obj
        else:
          return self._object_type(*args, **kwargs)

    symbols = {}

    for alias, symbol in symbol_table.items():
      registrar = Registrar(alias, symbol)
      symbols[alias] = registrar
      symbols[symbol] = registrar

    if aliases.objects:
      symbols.update(aliases.objects)

    # Compute "per path" symbols (which will all use the same mutable ParseContext).
    # TODO: See https://github.com/pantsbuild/pants/issues/3561
    parse_context = ParseContext(rel_path='', type_aliases=symbols)
    for alias, object_factory in aliases.context_aware_object_factories.items():
      symbols[alias] = object_factory(parse_context)

    for alias, target_macro_factory in aliases.target_macro_factories.items():
      underlying_symbol = symbols.get(alias, TargetAdaptor)
      symbols[alias] = target_macro_factory.target_macro(parse_context)
      for target_type in target_macro_factory.target_types:
        symbols[target_type] = Registrar(alias, underlying_symbol)

    # TODO: Replace builtins for paths with objects that will create wrapped PathGlobs objects.
    # The strategy for https://github.com/pantsbuild/pants/issues/3560 should account for
    # migrating these additional captured arguments to typed Sources.
    symbols['globs'] = Globs
    symbols['rglobs'] = RGlobs
    symbols['zglobs'] = ZGlobs
    symbols['bundle'] = BundleAdaptor

    return symbols, parse_context
コード例 #8
0
    def _instantiate_jvm_app(self, kwargs):
        """For JvmApp target, convert BundleAdaptor to BundleProps."""
        parse_context = ParseContext(kwargs['address'].spec_path, dict())
        bundleprops_factory = Bundle(parse_context)
        kwargs['bundles'] = [
            bundleprops_factory.create_bundle_props(bundle)
            for bundle in kwargs['bundles']
        ]

        return JvmApp(build_graph=self, **kwargs)
コード例 #9
0
    def _instantiate_app(self, target_cls: Type[TargetV1], kwargs) -> TargetV1:
        """For App targets, convert BundleAdaptor to BundleProps."""
        parse_context = ParseContext(kwargs["address"].spec_path, dict())
        bundleprops_factory = Bundle(parse_context)
        kwargs["bundles"] = [
            bundleprops_factory.create_bundle_props(bundle)
            for bundle in kwargs["bundles"]
        ]

        return target_cls(build_graph=self, **kwargs)
コード例 #10
0
ファイル: parser.py プロジェクト: codealchemy/pants
    def _generate_symbols(
        build_root: str,
        target_type_aliases: Iterable[str],
        object_aliases: BuildFileAliases,
        use_deprecated_python_macros: bool,
    ) -> tuple[dict[str, Any], ParseState]:
        # N.B.: We re-use the thread local ParseState across symbols for performance reasons.
        # This allows a single construction of all symbols here that can be re-used for each BUILD
        # file parse with a reset of the ParseState for the calling thread.
        parse_state = ParseState()

        class Registrar:
            def __init__(self, type_alias: str) -> None:
                self._type_alias = type_alias

            def __call__(self, **kwargs: Any) -> TargetAdaptor:
                # Target names default to the name of the directory their BUILD file is in
                # (as long as it's not the root directory).
                if "name" not in kwargs:
                    dirname = os.path.basename(parse_state.rel_path())
                    if not dirname:
                        raise UnaddressableObjectError(
                            "Targets in root-level BUILD files must be named explicitly."
                        )
                    kwargs["name"] = dirname
                target_adaptor = TargetAdaptor(self._type_alias, **kwargs)
                parse_state.add(target_adaptor)
                return target_adaptor

        symbols: dict[str, Any] = {
            **object_aliases.objects,
            "build_file_dir":
            lambda: PurePath(parse_state.rel_path()),
        }
        symbols.update((alias, Registrar(alias))
                       for alias in target_type_aliases
                       if not use_deprecated_python_macros
                       or alias not in _AMBIGUOUS_PYTHON_MACRO_SYMBOLS)

        parse_context = ParseContext(build_root=build_root,
                                     type_aliases=symbols,
                                     rel_path_oracle=parse_state)
        for alias, object_factory in object_aliases.context_aware_object_factories.items(
        ):
            if use_deprecated_python_macros or alias not in _AMBIGUOUS_PYTHON_MACRO_SYMBOLS:
                symbols[alias] = object_factory(parse_context)

        return symbols, parse_state
コード例 #11
0
ファイル: parser.py プロジェクト: zomglings/pants
    def _generate_symbols(
        target_type_aliases: Iterable[str],
        object_aliases: BuildFileAliases,
    ) -> Tuple[Dict[str, Any], ParseContext]:
        symbols: Dict[str, Any] = {}

        # Compute "per path" symbols.  For performance, we use the same ParseContext, which we
        # mutate to set the rel_path appropriately before it's actually used. This allows this
        # method to reuse the same symbols for all parses. Meanwhile, we set the rel_path to None,
        # so that we get a loud error if anything tries to use it before it's set.
        # TODO: See https://github.com/pantsbuild/pants/issues/3561
        parse_context = ParseContext(rel_path=None, type_aliases=symbols)

        class Registrar:
            def __init__(self, parse_context: ParseContext, type_alias: str):
                self._parse_context = parse_context
                self._type_alias = type_alias

            def __call__(self, *args, **kwargs):
                # Target names default to the name of the directory their BUILD file is in
                # (as long as it's not the root directory).
                if "name" not in kwargs:
                    dirname = os.path.basename(self._parse_context.rel_path)
                    if not dirname:
                        raise UnaddressableObjectError(
                            "Targets in root-level BUILD files must be named explicitly."
                        )
                    kwargs["name"] = dirname
                kwargs.setdefault("type_alias", self._type_alias)
                target_adaptor = TargetAdaptor(**kwargs)
                self._parse_context._storage.add(target_adaptor)
                return target_adaptor

        symbols.update({
            alias: Registrar(parse_context, alias)
            for alias in target_type_aliases
        })
        symbols.update(object_aliases.objects)
        for alias, object_factory in object_aliases.context_aware_object_factories.items(
        ):
            symbols[alias] = object_factory(parse_context)

        return symbols, parse_context
コード例 #12
0
  def _per_path_symbol_factory(cls, path, aliases, global_symbols):
    per_path_symbols = {}

    symbols = global_symbols.copy()
    for alias, target_macro_factory in aliases.target_macro_factories.items():
      for target_type in target_macro_factory.target_types:
        symbols[target_type] = Target

    parse_context = ParseContext(rel_path=os.path.dirname(path),
                                 type_aliases=symbols)

    for alias, object_factory in aliases.context_aware_object_factories.items():
      per_path_symbols[alias] = object_factory(parse_context)

    for alias, target_macro_factory in aliases.target_macro_factories.items():
      target_macro = target_macro_factory.target_macro(parse_context)
      per_path_symbols[alias] = target_macro
      for target_type in target_macro_factory.target_types:
        per_path_symbols[target_type] = Target

    return per_path_symbols
コード例 #13
0
def _bundle(rel_path):
    pc = ParseContext(rel_path=rel_path, type_aliases={})
    return Bundle(pc)
コード例 #14
0
    def _generate_symbols(symbol_table, aliases):
        symbols = {}

        # Compute "per path" symbols.  For performance, we use the same ParseContext, which we
        # mutate (in a critical section) to set the rel_path appropriately before it's actually used.
        # This allows this method to reuse the same symbols for all parses.  Meanwhile we set the
        # rel_path to None, so that we get a loud error if anything tries to use it before it's set.
        # TODO: See https://github.com/pantsbuild/pants/issues/3561
        parse_context = ParseContext(rel_path=None, type_aliases=symbols)

        class Registrar(BuildFileTargetFactory):
            def __init__(self, parse_context, type_alias, object_type):
                self._parse_context = parse_context
                self._type_alias = type_alias
                self._object_type = object_type
                self._serializable = Serializable.is_serializable_type(
                    self._object_type)

            @memoized_property
            def target_types(self):
                return [self._object_type]

            def __call__(self, *args, **kwargs):
                # Target names default to the name of the directory their BUILD file is in
                # (as long as it's not the root directory).
                if 'name' not in kwargs and issubclass(self._object_type,
                                                       TargetAdaptor):
                    dirname = os.path.basename(self._parse_context.rel_path)
                    if dirname:
                        kwargs['name'] = dirname
                    else:
                        raise UnaddressableObjectError(
                            'Targets in root-level BUILD files must be named explicitly.'
                        )
                name = kwargs.get('name')
                if name and self._serializable:
                    kwargs.setdefault('type_alias', self._type_alias)
                    obj = self._object_type(**kwargs)
                    self._parse_context._storage.add(obj)
                    return obj
                else:
                    return self._object_type(*args, **kwargs)

        for alias, symbol in symbol_table.table.items():
            registrar = Registrar(parse_context, alias, symbol)
            symbols[alias] = registrar
            symbols[symbol] = registrar

        if aliases.objects:
            symbols.update(aliases.objects)

        for alias, object_factory in aliases.context_aware_object_factories.items(
        ):
            symbols[alias] = object_factory(parse_context)

        for alias, target_macro_factory in aliases.target_macro_factories.items(
        ):
            underlying_symbol = symbols.get(alias, TargetAdaptor)
            symbols[alias] = target_macro_factory.target_macro(parse_context)
            for target_type in target_macro_factory.target_types:
                symbols[target_type] = Registrar(parse_context, alias,
                                                 underlying_symbol)

        # TODO: Replace builtins for paths with objects that will create wrapped PathGlobs objects.
        # The strategy for https://github.com/pantsbuild/pants/issues/3560 should account for
        # migrating these additional captured arguments to typed Sources.
        class GlobWrapper:
            def __init__(self, parse_context, glob_type):
                self._parse_context = parse_context
                self._glob_type = glob_type

            def __call__(self, *args, **kwargs):
                return self._glob_type(*args,
                                       spec_path=self._parse_context.rel_path,
                                       **kwargs)

        symbols['globs'] = GlobWrapper(parse_context, Globs)
        symbols['rglobs'] = GlobWrapper(parse_context, RGlobs)
        symbols['zglobs'] = GlobWrapper(parse_context, ZGlobs)

        symbols['bundle'] = BundleAdaptor

        return symbols, parse_context
コード例 #15
0
def _globs(rel_path):
    pc = ParseContext(rel_path=rel_path, type_aliases={})
    return Globs(pc)
コード例 #16
0
ファイル: parser.py プロジェクト: wisechengyi/pants
    def _generate_symbols(
        symbol_table: SymbolTable,
        aliases: BuildFileAliases,
    ) -> Tuple[Dict, ParseContext]:
        symbols: Dict = {}

        # Compute "per path" symbols.  For performance, we use the same ParseContext, which we
        # mutate (in a critical section) to set the rel_path appropriately before it's actually used.
        # This allows this method to reuse the same symbols for all parses.  Meanwhile we set the
        # rel_path to None, so that we get a loud error if anything tries to use it before it's set.
        # TODO: See https://github.com/pantsbuild/pants/issues/3561
        parse_context = ParseContext(rel_path=None, type_aliases=symbols)

        class Registrar(BuildFileTargetFactory):
            def __init__(self, parse_context, type_alias, object_type):
                self._parse_context = parse_context
                self._type_alias = type_alias
                self._object_type = object_type
                self._serializable = Serializable.is_serializable_type(
                    self._object_type)

            @memoized_property
            def target_types(self):
                return [self._object_type]

            def __call__(self, *args, **kwargs):
                # Target names default to the name of the directory their BUILD file is in
                # (as long as it's not the root directory).
                if "name" not in kwargs and issubclass(self._object_type,
                                                       TargetAdaptor):
                    dirname = os.path.basename(self._parse_context.rel_path)
                    if dirname:
                        kwargs["name"] = dirname
                    else:
                        raise UnaddressableObjectError(
                            "Targets in root-level BUILD files must be named explicitly."
                        )
                name = kwargs.get("name")
                if name and self._serializable:
                    kwargs.setdefault("type_alias", self._type_alias)
                    obj = self._object_type(**kwargs)
                    self._parse_context._storage.add(obj)
                    return obj
                else:
                    return self._object_type(*args, **kwargs)

        for alias, symbol in symbol_table.table.items():
            registrar = Registrar(parse_context, alias, symbol)
            symbols[alias] = registrar
            symbols[symbol] = registrar

        if aliases.objects:
            symbols.update(aliases.objects)

        for alias, object_factory in aliases.context_aware_object_factories.items(
        ):
            symbols[alias] = object_factory(parse_context)

        for alias, target_macro_factory in aliases.target_macro_factories.items(
        ):
            underlying_symbol = symbols.get(alias, TargetAdaptor)
            symbols[alias] = target_macro_factory.target_macro(parse_context)
            for target_type in target_macro_factory.target_types:
                symbols[target_type] = Registrar(parse_context, alias,
                                                 underlying_symbol)

        symbols["bundle"] = BundleAdaptor

        return symbols, parse_context