:py:mod:`anod.spec` =================== .. py:module:: anod.spec .. autoapi-nested-parse:: Anod specification base class and API. Module Contents --------------- Classes ~~~~~~~ .. autoapisummary:: anod.spec.Anod Functions ~~~~~~~~~ .. autoapisummary:: anod.spec.check_api_version anod.spec.parse_command anod.spec.has_primitive anod.spec.fetch_attr Attributes ~~~~~~~~~~ .. autoapisummary:: anod.spec.__version__ anod.spec.SUPPORTED_API anod.spec.logger anod.spec.spec_logger anod.spec.BUILD_PRIMITIVE .. py:data:: __version__ :value: '1.4' .. py:data:: SUPPORTED_API :value: () .. py:data:: logger .. py:data:: spec_logger .. py:data:: BUILD_PRIMITIVE .. py:function:: check_api_version(version: str) -> None Make sure there are no API mismatch. :param version: the API version to check :raise: AnodError if the API is not supported .. py:function:: parse_command(command: collections.abc.Sequence[str], build_space: e3.anod.buildspace.BuildSpace) -> list[str] Parse a command line formatting each string. :param command: the command line (a list of string) :param build_space: a build space object .. py:function:: has_primitive(anod_instance: Anod, name: Literal[download] | PRIMITIVE) -> bool Return True if the primitive `name` is supported. Note that download is currently considered as a primitive in that context. :param anod_instance: an Anod instance :param name: name of the primitive ('build', 'install'...) .. py:function:: fetch_attr(instance: Any, name: str, default_value: Any) -> Any Return an attribute or the default value if missing. Unlike `getattr(instance, name, default_value)`, this works only on attributes present in the class (so class attributes or properties) and this does not hide AttributeError exceptions that getting an existing attribute might raise. :param instance: the object instance :param name: the attribute name :param default_value: the default value to return if attribute is missing .. py:class:: Anod(qualifier: str | dict[str, str | bool | collections.abc.Iterable[str]] | None, kind: PRIMITIVE, jobs: int = 1, env: e3.env.BaseEnv | None = None, *, parse_qualifiers: bool = True) Anod base class. To write an Anod specification file, you'll need to subclass Anod. A very basic Anod specification file could be: .. code-block:: python from e3.anod.spec import Anod class MyProduct(Anod): pass All attributes starting with ``spec_`` are reserved by the driver and must not be overwritten. Several attributes are set when loading the spec: :cvar api_version: which API version is in use :cvar data_files: set of yaml files associated with the spec :cvar spec_checksum: the sha1 of the specification file content :cvar spec_dir: directory where the specification files are located :cvar name: the basename of the specification file (without the .anod extension) :cvar sandbox: e3.anod.sandbox.SandBox object shared by all Anod instances :vartype sandbox: e3.anod.sandbox.SandBox | None Some attributes are meant to be overwritten in the specification file: :cvar source_pkg_build: a dictionary associating Anod.SourceBuilder to the Anod.Source names Some attributes are here to simply the writing of specification files. They are part of the Anod API: :cvar Dependency: the e3.anod.deps.Dependency class :cvar Package: the e3.anod.package.Package class :cvar Source: the e3.anod.package.Source class :cvar SourceBuilder: the e3.anod.package.SourceBuilder class :cvar ThirdPartySourceBuilder: the e3.anod.package.ThirdPartySourceBuilder :ivar uid: unique identifier for the instance, None until the instance has been activated with AnodDriver.activate() :vartype uid: str | None .. py:property:: qualifier :type: str Return the qualifier string representation (deprecated in API 1.7+). :return: qualifier string from parsed_qualifier dict .. py:property:: enable_name_generator :type: bool State if the name generation must be enabled. If true, then both the 'component' and the 'build_space_name' are generated. .. py:property:: readme_info :type: tuple[str, str] | None Return readme location and final filename. .. note:: This property make sens only if a component is declared. :return: A tuple with a relative path to spec directory where the find the content and the final basename for the readme. .. py:property:: args :type: dict[str, str | bool | frozenset[str]] Access to final qualifier values (with defaults set). .. py:property:: base_name :type: str Set the base name used for the name generation. This method is used to provide the base name to be used by the name generator. By default, this base name is 'self.name' (the spec name without .anod). It can be overloaded in the user spec. .. py:property:: build_space_name :type: str Return an automatic build_space_name. If the component name is not None (from the component method), it will return the component name for consistency reasons. :return: self.name if the name generator is disabled and the generated build_space name otherwise. :rtype: str | None .. py:property:: build_space :type: e3.anod.buildspace.BuildSpace Return the build space associated with this spec instance. :return: BuildSpace object :raise AnodError: if build space has not been set .. py:property:: has_package :type: bool Return true if the spec defines a binary package. .. py:property:: package :type: e3.anod.package.Package | None Return binary package creation recipe. If None do not create a binary package, needs a component name set. .. py:property:: component :type: str | None Return component name. If None, do not create a component (nor a binary package). :return: None if the name generator is disabled and the generated name otherwise (possibly None if no component is required) .. py:property:: module_name :type: str For backward compatibility purpose. .. py:property:: anod_id :type: str For backward compatibility purpose. .. py:property:: source_pkg_build :type: list[e3.anod.package.SourceBuilder] | None Return list of SourceBuilder defined in the specification file. .. py:attribute:: spec_checksum :value: '' .. py:attribute:: spec_dir :value: '' .. py:attribute:: sandbox :type: e3.anod.sandbox.SandBox | None .. py:attribute:: name :value: '' .. py:attribute:: api_version .. py:attribute:: data_files :type: tuple[str, Ellipsis] :value: () .. py:attribute:: Dependency .. py:attribute:: Package .. py:attribute:: BuildVar .. py:attribute:: Source .. py:attribute:: SharedSource .. py:attribute:: SourceBuilder .. py:attribute:: ExternalSourceBuilder .. py:attribute:: ThirdPartySourceBuilder .. py:method:: declare_qualifiers_and_components(qualifiers_manager: e3.anod.qualifiers_manager.QualifiersManager) -> None Configure all the qualifiers and components. This method must be overridden in the user spec to actually configure the QualifiersManager. All the qualifiers must be declared using the declare_tag_qualifier and declare_key_value_qualifier spec_parameter_manager method. All the components must be declared using the declare_component method of QualifiersManager class. :param qualifiers_manager: the QualifiersManager instance to be configured. .. py:method:: bind_to_sandbox(sandbox: e3.anod.sandbox.SandBox) -> None Bind spec instance to a physical Anod sandbox. Binding an Anod instance to a sandbox will set the build_space attribute. :param sandbox: the sandbox to bind to .. py:method:: check_shared_libraries_closure(prefix: str | None = None, ignored_libs: list[str] | None = None, ldd_output: str | None = None, case_sensitive: bool | None = None) -> dict[str, list[tuple[str, str]]] Sanity check the shared library closure. Make sure that the libraries only depend on authorized system shared libraries. Raise an error when a problem is detected. It is possible to use the *ldd_output* parameter to mimic the ``ldd`` call. In that case, the *ldd_output* should look like:: /a/b/c.so: d.so => /e/f/d.so g.so => /a/b/g.so /a/b/h.so: g.so => /a/b/g.so .. note:: Indented lines above use the TAB character. .. note:: This method may be used only on hosts with an ``ldd`` tool in the ``PATH``. If the tool may not be found with :func:`~e3.os.fs.which`, and *ldd_output* is not provided, a :exc:`FileNotFoundError` exception is raised. :param prefix: The path where to find the library to be checked. :param ignored_libs: The list of additional system libraries authorized in the closure. :param ldd_output: An ``ldd`` command output. :param case_sensitive: State if the comparison of a library name and the value in *ignored_libs* should be case-sensitive or not. If ``None``, the comparison is case-sensitive, but on Windows hosts. :return: A dictionary, where keys are the analyzed files, and the values are the shared libraries linked to that file (a tuple made of the file name and its path). :raise AnodError: if some of the shared libraries in *prefix* (or in *ldd_output*) is not in the same directory as the analysed element. :raise FileNotFoundError: if *ldd_output* is not provided and ``ldd`` application cannot be found in the ``PATH``. .. py:method:: load_config_file(extended: bool = False, suffix: str | None = None, selectors: dict | None = None) -> Any Load a YAML config file associated with the current module. This function looks for a YAML starting with the spec basename. The list of available file is set by the data_files parameter when initializing the spec. :param suffix: suffix of the configuration file (default is None) :param extended: if True then a special yaml parser is used with ability to use case statement :param selectors: additional selectors for extended mode .. py:method:: __getitem__(key: str) -> Any Access build_space attributes and pre callback values directly. Allow accessing all build_space attributes directly by using __getitem__, e.g. self['PKG_DIR'] to access self.build_space.pkg_dir values. Also, directly access items returned by the ``pre`` callback. :param key: the attribute name to access .. py:method:: get_qualifier(qualifier_name: str) -> e3.anod.qualifiers_manager.QualifierValue | None Return a qualifier value. Requires that qualifiers_manager attribute has been initialized and its parse method called :param qualifier_name: the qualifier name. :return: The qualifier value: - A string for key value qualifiers - A bool for tag qualifiers - ``None`` if the name_generator is disabled .. py:method:: primitive(pre: str | None = None, post: str | None = None, version: collections.abc.Callable[Ellipsis, str] | None = None, require: collections.abc.Callable[[Anod], bool] | None = None, post_install: bool = False) -> collections.abc.Callable :classmethod: Declare an anod primitive. Catch all exceptions and raise AnodError with the traceback :param pre: None or name of method in the spec to call before running the primitive. The method takes a unique parameter `self` and returns a dict :param post: None or "install". This parameter is obsolete and should not be used. Prefer "post_install=True" to achieve the same effect :param version: None or a callback function returning the version that will be evaluated as a string. This callback is called after running the primitive :param require: None or a special function to call before running the primitive. The function takes a unique parameter `self` and returns a boolean :param post_install: if True call the install primitive after the build primitive. Note that between the two a binary package might be generated depending on the context. This is equivalent to post="install" :raise: AnodError .. py:method:: shell(*command: str, parse_shebang: bool = True, output: e3.os.process.DEVNULL_VALUE | e3.os.process.PIPE_VALUE | str | IO | None = None, python_executable: None = None, **kwargs: Any) -> e3.os.process.Run Run a subprocess using e3.os.process.Run. Contrary to what is done in e3.os.process.Run parse_shebang defaults to True and output is by default set to the anod build space log stream. Note that calling shell() raises an exception when the process returns an exit code that is not 0. Same options as e3.os.process.Run with some small differences: :param python_executable: kept for backward compatibility but ignored :param output: by default set to anod build space log stream :param parse_shebang: by default set True :raise: ShellError