#
#  Copyright (C) 2016-2020 Codethink Limited
#  Copyright (C) 2017-2020 Bloomberg Finance LP
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU Lesser General Public
#  License as published by the Free Software Foundation; either
#  version 2 of the License, or (at your option) any later version.
#
#  This library is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
#  Lesser General Public License for more details.
#
#  You should have received a copy of the GNU Lesser General Public
#  License along with this library. If not, see <http://www.gnu.org/licenses/>.
#
#  Authors:
#        Tristan Van Berkom <tristan.vanberkom@codethink.co.uk>

"""
Element - Base element class
============================


.. _core_element_abstract_methods:

Abstract Methods
----------------
For loading and configuration purposes, Elements must implement the
:ref:`Plugin base class abstract methods <core_plugin_abstract_methods>`.


.. _core_element_build_phase:

Build Phase
~~~~~~~~~~~
The following methods are the foundation of the element's *build
phase*, they must be implemented by all Element classes, unless
explicitly stated otherwise.

* :func:`Element.configure_sandbox() <buildstream.element.Element.configure_sandbox>`

  Configures the :class:`.Sandbox`. This is called before anything else

* :func:`Element.stage() <buildstream.element.Element.stage>`

  Stage dependencies and :class:`Sources <buildstream.source.Source>` into
  the sandbox.

* :func:`Element.prepare() <buildstream.element.Element.prepare>`

  Call preparation methods that should only be performed once in the
  lifetime of a build directory (e.g. autotools' ./configure).

  **Optional**: If left unimplemented, this step will be skipped.

* :func:`Element.assemble() <buildstream.element.Element.assemble>`

  Perform the actual assembly of the element


Miscellaneous
~~~~~~~~~~~~~
Miscellaneous abstract methods also exist:

* :func:`Element.generate_script() <buildstream.element.Element.generate_script>`

  For the purpose of ``bst source checkout --include-build-scripts``, an Element may optionally implement this.


Class Reference
---------------
"""

import os
import re
import stat
import copy
import warnings
import contextlib
from contextlib import contextmanager, suppress
from functools import partial
from itertools import chain
import string
from typing import cast, TYPE_CHECKING, Any, Dict, Iterator, List, Optional, Set, Sequence

from pyroaring import BitMap  # pylint: disable=no-name-in-module
from ruamel import yaml

from . import _yaml
from ._variables import Variables
from ._versions import BST_CORE_ARTIFACT_VERSION
from ._exceptions import BstError, LoadError, ImplError, SourceCacheError, CachedFailure
from .exceptions import ErrorDomain, LoadErrorReason
from .utils import FileListResult, BST_ARBITRARY_TIMESTAMP
from . import utils
from . import _cachekey
from . import _site
from .node import Node
from .plugin import Plugin
from .sandbox import SandboxFlags, SandboxCommandError
from .sandbox._config import SandboxConfig
from .sandbox._sandboxremote import SandboxRemote
from .types import _Scope, _CacheBuildTrees, _KeyStrength, OverlapAction, _DisplayKey
from ._artifact import Artifact
from ._elementproxy import ElementProxy
from ._elementsources import ElementSources
from ._loader import Symbol, DependencyType, MetaSource
from ._overlapcollector import OverlapCollector

from .storage.directory import Directory
from .storage._filebaseddirectory import FileBasedDirectory
from .storage.directory import VirtualDirectoryError

if TYPE_CHECKING:
    from typing import Tuple
    from .node import MappingNode, ScalarNode, SequenceNode
    from .types import SourceRef

    # pylint: disable=cyclic-import
    from .sandbox import Sandbox
    from .source import Source
    from ._context import Context
    from ._loader import LoadElement
    from ._project import Project

    # pylint: enable=cyclic-import


class ElementError(BstError):
    """This exception should be raised by :class:`.Element` implementations
    to report errors to the user.

    Args:
       message: The error message to report to the user
       detail: A possibly multiline, more detailed error message
       reason: An optional machine readable reason string, used for test cases
       collect: An optional directory containing partial install contents
       temporary: An indicator to whether the error may occur if the operation was run again.
    """

    def __init__(
        self, message: str, *, detail: str = None, reason: str = None, collect: str = None, temporary: bool = False
    ):
        super().__init__(message, detail=detail, domain=ErrorDomain.ELEMENT, reason=reason, temporary=temporary)

        self.collect = collect


class DependencyConfiguration:
    """An object representing the configuration of a dependency

    This is used to provide dependency configurations for elements which implement
    :func:`Element.configure_dependencies() <buildstream.element.Element.configure_dependencies>`
    """

    def __init__(self, element: "Element", path: str, config: Optional["MappingNode"]):

        self.element = element  # type: Element
        """The dependency Element"""

        self.path = path  # type: str
        """The path used to refer to this dependency"""

        self.config = config  # type: Optional[MappingNode]
        """The custom :term:`dependency configuration <Dependency configuration>`, or ``None``
        if no custom configuration was provided"""


class Element(Plugin):
    """Element()

    Base Element class.

    All elements derive from this class, this interface defines how
    the core will be interacting with Elements.
    """

    # The defaults from the yaml file and project
    __defaults = None
    # A hash of Element by LoadElement
    __instantiated_elements = {}  # type: Dict[LoadElement, Element]
    # A list of (source, ref) tuples which were redundantly specified
    __redundant_source_refs = []  # type: List[Tuple[Source, SourceRef]]

    BST_ARTIFACT_VERSION = 0
    """The element plugin's artifact version

    Elements must first set this to 1 if they change their unique key
    structure in a way that would produce a different key for the
    same input, or introduce a change in the build output for the
    same unique key. Further changes of this nature require bumping the
    artifact version.
    """

    BST_STRICT_REBUILD = False
    """Whether to rebuild this element in non strict mode if
    any of the dependencies have changed.
    """

    BST_FORBID_RDEPENDS = False
    """Whether to raise exceptions if an element has runtime dependencies.
    """

    BST_FORBID_BDEPENDS = False
    """Whether to raise exceptions if an element has build dependencies.
    """

    BST_FORBID_SOURCES = False
    """Whether to raise exceptions if an element has sources.
    """

    BST_RUN_COMMANDS = True
    """Whether the element may run commands using Sandbox.run.
    """

    BST_ELEMENT_HAS_ARTIFACT = True
    """Whether the element produces an artifact when built.
    """

    def __init__(
        self,
        context: "Context",
        project: "Project",
        load_element: "LoadElement",
        plugin_conf: Dict[str, Any],
        *,
        artifact: Artifact = None,
    ):

        self.__cache_key_dict = None  # Dict for cache key calculation
        self.__cache_key: Optional[str] = None  # Our cached cache key

        super().__init__(load_element.name, context, project, load_element.node, "element")

        # Ensure the project is fully loaded here rather than later on
        if not load_element.first_pass:
            project.ensure_fully_loaded()

        self.project_name = self._get_project().name
        """The :ref:`name <project_format_name>` of the owning project

        .. attention::

           Combining this attribute with :attr:`Plugin.name <buildstream.plugin.Plugin.name>`
           does not provide a unique identifier for an element within a project, this is because
           multiple :mod:`junction <elements.junction>` elements can be used specify the same
           project as a subproject.
        """

        self.normal_name = _get_normal_name(self.name)
        """A normalized element name

        This is the original element without path separators or
        the extension, it's used mainly for composing log file names
        and creating directory names and such.
        """

        #
        # Internal instance properties
        #
        self._depth = None  # Depth of Element in its current dependency graph
        self._overlap_collector = None  # type: Optional[OverlapCollector]

        #
        # Private instance properties
        #

        # Cache of proxies instantiated, indexed by the proxy owner
        self.__proxies = {}  # type: Dict[Element, ElementProxy]
        # Direct runtime dependency Elements
        self.__runtime_dependencies = []  # type: List[Element]
        # Direct build dependency Elements
        self.__build_dependencies = []  # type: List[Element]
        # Direct build dependency subset which require strict rebuilds
        self.__strict_dependencies = []  # type: List[Element]
        # Direct reverse build dependency Elements
        self.__reverse_build_deps = set()  # type: Set[Element]
        # Direct reverse runtime dependency Elements
        self.__reverse_runtime_deps = set()  # type: Set[Element]
        self.__build_deps_uncached = None  # Build dependencies which are not yet cached
        self.__runtime_deps_uncached = None  # Runtime dependencies which are not yet cached
        self.__ready_for_runtime_and_cached = False  # Whether all runtime deps are cached, as well as the element
        self.__cached_remotely = None  # Whether the element is cached remotely
        self.__sources = ElementSources(context, project, self)  # The element sources
        self.__weak_cache_key: Optional[str] = None  # Our cached weak cache key
        self.__strict_cache_key: Optional[str] = None  # Our cached cache key for strict builds
        self.__artifacts = context.artifactcache  # Artifact cache
        self.__sourcecache = context.sourcecache  # Source cache
        self.__assemble_scheduled = False  # Element is scheduled to be assembled
        self.__assemble_done = False  # Element is assembled
        self.__pull_done = False  # Whether pull was attempted
        self.__cached_successfully = None  # If the Element is known to be successfully cached
        self.__splits = None  # Resolved regex objects for computing split domains
        self.__whitelist_regex = None  # Resolved regex object to check if file is allowed to overlap
        self.__tainted = None  # Whether the artifact is tainted and should not be shared
        self.__required = False  # Whether the artifact is required in the current session
        self.__artifact_files_required = False  # Whether artifact files are required in the local cache
        self.__build_result = None  # The result of assembling this Element (success, description, detail)
        # Artifact class for direct artifact composite interaction
        self.__artifact = None  # type: Optional[Artifact]
        self.__sandbox_config = None  # type: Optional[SandboxConfig]

        self.__batch_prepare_assemble = False  # Whether batching across prepare()/assemble() is configured
        self.__batch_prepare_assemble_flags = 0  # Sandbox flags for batching across prepare()/assemble()
        # Collect dir for batching across prepare()/assemble()
        self.__batch_prepare_assemble_collect = None  # type: Optional[str]

        # Callbacks
        self.__required_callback = None  # Callback to Queues
        self.__can_query_cache_callback = None  # Callback to PullQueue/FetchQueue
        self.__buildable_callback = None  # Callback to BuildQueue

        self.__resolved_initial_state = False  # Whether the initial state of the Element has been resolved

        self.__environment: Dict[str, str] = {}
        self.__variables: Optional[Variables] = None
        self.__public: "MappingNode" = Node.from_dict({})

        if artifact:
            self.__initialize_from_artifact(artifact)
        else:
            self.__initialize_from_yaml(load_element, plugin_conf)

    def __lt__(self, other):
        return self.name < other.name

    #############################################################
    #                      Abstract Methods                     #
    #############################################################
    def configure_dependencies(self, dependencies: List[DependencyConfiguration]) -> None:
        """Configure the Element with regards to it's build dependencies

        Elements can use this method to parse custom configuration which define their
        relationship to their build dependencies.

        If this method is implemented, then it will be called with all direct build dependencies
        specified in their :ref:`element declaration <format_dependencies>` in a list.

        If the dependency was declared with custom configuration, it will be provided along
        with the dependency element, otherwise `None` will be passed with dependencies which
        do not have any additional configuration.

        If the user has specified the same build dependency multiple times with differing
        configurations, then those build dependencies will be provided multiple times
        in the ``dependencies`` list.

        Args:
           dependencies (list): A list of :class:`DependencyConfiguration <buildstream.element.DependencyConfiguration>`
                                objects

        Raises:
           :class:`.ElementError`: When the element raises an error

        The format of the :class:`MappingNode <buildstream.node.MappingNode>` provided as
        :attr:`DependencyConfiguration.config <buildstream.element.DependencyConfiguration.config>
        belongs to the implementing element, and as such the format should be documented by the plugin,
        and the :func:`MappingNode.validate_keys() <buildstream.node.MappingNode.validate_keys>`
        method should be called by the implementing plugin in order to validate it.

        .. note::

           It is unnecessary to implement this method if the plugin does not support
           any custom :term:`dependency configuration <Dependency configuration>`.
        """
        # This method is not called on plugins which do not implement it, so it would
        # be a bug if this accidentally gets called.
        #
        assert False, "Code should not be reached"

    def configure_sandbox(self, sandbox: "Sandbox") -> None:
        """Configures the the sandbox for execution

        Args:
           sandbox: The build sandbox

        Raises:
           (:class:`.ElementError`): When the element raises an error

        Elements must implement this method to configure the sandbox object
        for execution.
        """
        raise ImplError("element plugin '{kind}' does not implement configure_sandbox()".format(kind=self.get_kind()))

    def stage(self, sandbox: "Sandbox") -> None:
        """Stage inputs into the sandbox directories

        Args:
           sandbox: The build sandbox

        Raises:
           (:class:`.ElementError`): When the element raises an error

        Elements must implement this method to populate the sandbox
        directory with data. This is done either by staging :class:`.Source`
        objects, by staging the artifacts of the elements this element depends
        on, or both.
        """
        raise ImplError("element plugin '{kind}' does not implement stage()".format(kind=self.get_kind()))

    def prepare(self, sandbox: "Sandbox") -> None:
        """Run one-off preparation commands.

        This is run before assemble(), but is guaranteed to run only
        the first time if we build incrementally - this makes it
        possible to run configure-like commands without causing the
        entire element to rebuild.

        Args:
           sandbox: The build sandbox

        Raises:
           (:class:`.ElementError`): When the element raises an error

        By default, this method does nothing, but may be overriden to
        allow configure-like commands.
        """

    def assemble(self, sandbox: "Sandbox") -> str:
        """Assemble the output artifact

        Args:
           sandbox: The build sandbox

        Returns:
           An absolute path within the sandbox to collect the artifact from

        Raises:
           (:class:`.ElementError`): When the element raises an error

        Elements must implement this method to create an output
        artifact from its sources and dependencies.
        """
        raise ImplError("element plugin '{kind}' does not implement assemble()".format(kind=self.get_kind()))

    def generate_script(self) -> str:
        """Generate a build (sh) script to build this element

        Returns:
           A string containing the shell commands required to build the element

        BuildStream guarantees the following environment when the
        generated script is run:

        - All element variables have been exported.
        - The cwd is `self.get_variable('build-root')/self.normal_name`.
        - $PREFIX is set to `self.get_variable('install-root')`.
        - The directory indicated by $PREFIX is an empty directory.

        Files are expected to be installed to $PREFIX.

        If the script fails, it is expected to return with an exit
        code != 0.
        """
        raise ImplError("element plugin '{kind}' does not implement write_script()".format(kind=self.get_kind()))

    #############################################################
    #                       Public Methods                      #
    #############################################################
    def sources(self) -> Iterator["Source"]:
        """A generator function to enumerate the element sources

        Yields:
           The sources of this element
        """
        return self.__sources.sources()

    def dependencies(self, selection: Sequence["Element"] = None, *, recurse: bool = True) -> Iterator["Element"]:
        """A generator function which yields the build dependencies of the given element.

        This generator gives the Element access to all of the dependencies which it is has
        access to at build time. As explained in :ref:`the dependency type documentation <format_dependencies_types>`,
        this includes the direct build dependencies of the element being built, along with any
        transient runtime dependencies of those build dependencies.

        Subsets of the dependency graph can be selected using the `selection` argument,, which
        must consist of dependencies of this element. If the `selection` argument is specified as
        `None`, then the `self` element on which this is called is used as the `selection`.

        If `recurse` is specified (the default), the full dependencies will be listed
        in deterministic staging order, starting with the basemost elements. Otherwise,
        if `recurse` is not specified then only the direct dependencies will be traversed.

        Args:
           selection (Sequence[Element]): A list of dependencies to select, or None
           recurse (bool): Whether to recurse

        Yields:
           The dependencies of the selection, in deterministic staging order
        """
        #
        # In this public API, we ensure the invariant that an element can only
        # ever see elements in it's own _Scope.BUILD scope.
        #
        #  - Yield ElementProxy objects for every element except for the self element
        #  - When a selection is provided, ensure that we call the real _dependencies()
        #    method using _Scope.RUNTIME
        #  - When iterating over the self element, use _Scope.BUILD
        #
        visited = (BitMap(), BitMap())
        if selection is None:
            selection = [self]

        for element in selection:
            if element is self:
                scope = _Scope.BUILD
            else:
                scope = _Scope.RUN

            # Elements in the `selection` will actually be `ElementProxy` objects, but
            # those calls will be forwarded to their actual internal `_dependencies()`
            # methods.
            #
            for dep in element._dependencies(scope, recurse=recurse, visited=visited):
                yield cast("Element", dep.__get_proxy(self))

    def search(self, name: str) -> Optional["Element"]:
        """Search for a dependency by name

        Args:
           name: The dependency to search for

        Returns:
           The dependency element, or None if not found.
        """
        search = self._search(_Scope.BUILD, name)
        if search is self:
            return self
        elif search:
            return cast("Element", search.__get_proxy(self))

        return None

    def node_subst_vars(self, node: "ScalarNode") -> str:
        """Replace any variables in the string contained in the node and returns it.

        **Warning**: The method is deprecated and will get removed in the next version

        Args:
           node: A ScalarNode loaded from YAML

        Returns:
           The value with all variables replaced

        Raises:
           :class:`.LoadError`: When the node doesn't contain a string or a variable was not found.

        **Example:**

        .. code:: python

          # Expect a string 'name' in 'node', substituting any
          # variables in the returned string
          name = self.node_subst_vars(node.get_scalar('name'))
        """
        # FIXME: remove this
        warnings.warn(
            "configuration is now automatically expanded, this is a no-op and will be removed.", DeprecationWarning
        )
        return node.as_str()

    def node_subst_sequence_vars(self, node: "SequenceNode[ScalarNode]") -> List[str]:
        """Substitute any variables in the given sequence

        **Warning**: The method is deprecated and will get removed in the next version

        Args:
          node: A SequenceNode loaded from YAML

        Returns:
          The list with every variable replaced

        Raises:
          :class:`.LoadError`

        """
        # FIXME: remove this
        warnings.warn(
            "configuration is now automatically expanded, this is a no-op and will be removed.", DeprecationWarning
        )
        return node.as_str_list()

    def compute_manifest(
        self, *, include: Optional[List[str]] = None, exclude: Optional[List[str]] = None, orphans: bool = True
    ) -> str:
        """Compute and return this element's selective manifest

        The manifest consists on the list of file paths in the
        artifact. The files in the manifest are selected according to
        `include`, `exclude` and `orphans` parameters. If `include` is
        not specified then all files spoken for by any domain are
        included unless explicitly excluded with an `exclude` domain.

        Args:
           include: An optional list of domains to include files from
           exclude: An optional list of domains to exclude files from
           orphans: Whether to include files not spoken for by split domains

        Yields:
           The paths of the files in manifest
        """
        self.__assert_cached()
        return self.__compute_splits(include, exclude, orphans)

    def get_artifact_name(self, key: Optional[str] = None) -> str:
        """Compute and return this element's full artifact name

        Generate a full name for an artifact, including the project
        namespace, element name and cache key.

        This can also be used as a relative path safely, and
        will normalize parts of the element name such that only
        digits, letters and some select characters are allowed.

        Args:
           key: The element's cache key. Defaults to None

        Returns:
           The relative path for the artifact
        """
        if key is None:
            key = self._get_cache_key()

        assert key is not None

        return _compose_artifact_name(self.project_name, self.normal_name, key)

    def stage_artifact(
        self,
        sandbox: "Sandbox",
        *,
        path: str = None,
        action: str = OverlapAction.WARNING,
        include: Optional[List[str]] = None,
        exclude: Optional[List[str]] = None,
        orphans: bool = True,
    ) -> FileListResult:
        """Stage this element's output artifact in the sandbox

        This will stage the files from the artifact to the sandbox at specified location.
        The files are selected for staging according to the `include`, `exclude` and `orphans`
        parameters; if `include` is not specified then all files spoken for by any domain
        are included unless explicitly excluded with an `exclude` domain.

        Args:
           sandbox: The build sandbox
           path: An optional sandbox relative path
           action (OverlapAction): The action to take when overlapping with previous invocations
           include: An optional list of domains to include files from
           exclude: An optional list of domains to exclude files from
           orphans: Whether to include files not spoken for by split domains

        Raises:
           (:class:`.ElementError`): If the element has not yet produced an artifact.

        Returns:
           The result describing what happened while staging

        .. note::

           Directories in `dest` are replaced with files from `src`,
           unless the existing directory in `dest` is not empty in
           which case the path will be reported in the return value.

        .. attention::

           When staging artifacts with their dependencies, use
           :func:`Element.stage_dependency_artifacts() <buildstream.element.Element.stage_dependency_artifacts>`
           instead.
        """
        assert self._overlap_collector is not None, "Attempted to stage artifacts outside of Element.stage()"

        #
        # The public API can only be called on the implementing plugin itself.
        #
        # ElementProxy calls to stage_artifact() are routed directly to _stage_artifact(),
        # and the ElementProxy takes care of starting and ending the OverlapCollector session.
        #
        with self._overlap_collector.session(action, path):
            result = self._stage_artifact(
                sandbox, path=path, action=action, include=include, exclude=exclude, orphans=orphans
            )

        return result

    def stage_dependency_artifacts(
        self,
        sandbox: "Sandbox",
        selection: Sequence["Element"] = None,
        *,
        path: str = None,
        action: str = OverlapAction.WARNING,
        include: Optional[List[str]] = None,
        exclude: Optional[List[str]] = None,
        orphans: bool = True,
    ) -> None:
        """Stage element dependencies in scope

        This is primarily a convenience wrapper around
        :func:`Element.stage_artifact() <buildstream.element.Element.stage_artifact>`
        which takes care of staging all the dependencies in staging order and issueing the
        appropriate warnings.

        The `selection` argument will behave in the same was as specified by
        :func:`Element.dependencies() <buildstream.element.Element.dependencies>`,
        If the `selection` argument is specified as `None`, then the `self` element on which this
        is called is used as the `selection`.

        Args:
           sandbox (Sandbox): The build sandbox
           selection (Sequence[Element]): A list of dependencies to select, or None
           path (str): An optional sandbox relative path
           action (OverlapAction): The action to take when overlapping with previous invocations
           include (List[str]): An optional list of domains to include files from
           exclude (List[str]): An optional list of domains to exclude files from
           orphans (bool): Whether to include files not spoken for by split domains

        Raises:
           (:class:`.ElementError`): if forbidden overlaps occur.
        """
        assert self._overlap_collector is not None, "Attempted to stage artifacts outside of Element.stage()"

        with self._overlap_collector.session(action, path):
            for dep in self.dependencies(selection):
                dep._stage_artifact(sandbox, path=path, include=include, exclude=exclude, orphans=orphans, owner=self)

    def integrate(self, sandbox: "Sandbox") -> None:
        """Integrate currently staged filesystem against this artifact.

        Args:
           sandbox: The build sandbox

        This modifies the sysroot staged inside the sandbox so that
        the sysroot is *integrated*. Only an *integrated* sandbox
        may be trusted for running the software therein, as the integration
        commands will create and update important system cache files
        required for running the installed software (such as the ld.so.cache).
        """
        bstdata = self.get_public_data("bst")
        environment = self.get_environment()

        if bstdata is not None:
            with sandbox.batch(SandboxFlags.NONE):
                for command in bstdata.get_str_list("integration-commands", []):
                    sandbox.run(["sh", "-e", "-c", command], 0, env=environment, cwd="/", label=command)

    def stage_sources(self, sandbox: "Sandbox", directory: str) -> None:
        """Stage this element's sources to a directory in the sandbox

        Args:
           sandbox: The build sandbox
           directory: An absolute path within the sandbox to stage the sources at
        """
        self._stage_sources_in_sandbox(sandbox, directory)

    def get_public_data(self, domain: str) -> "MappingNode[Node]":
        """Fetch public data on this element

        Args:
           domain: A public domain name to fetch data for

        Returns:
           The public data for the requested *domain*, if *domain* does not exist
           for this element, then an empty node will be returned.
        """
        data = self.__public.get_mapping(domain, default={})
        return data.clone()

    def get_environment(self) -> Dict[str, str]:
        """Fetch the environment suitable for running in the sandbox

        Returns:
           A dictionary of string key/values suitable for passing
           to :func:`Sandbox.run() <buildstream.sandbox.Sandbox.run>`
        """
        return self.__environment

    def get_variable(self, varname: str) -> Optional[str]:
        """Fetch the value of a variable resolved for this element.

        Args:
           varname: The name of the variable to fetch

        Returns:
           The resolved value for *varname*, or None if no
           variable was declared with the given name.
        """
        assert self.__variables
        return self.__variables.get(varname)

    def batch_prepare_assemble(self, flags: int, *, collect: Optional[str] = None) -> None:
        """ Configure command batching across prepare() and assemble()

        Args:
           flags: The sandbox flags for the command batch
           collect: An optional directory containing partial install contents
                    on command failure.

        This may be called in :func:`Element.configure_sandbox() <buildstream.element.Element.configure_sandbox>`
        to enable batching of all sandbox commands issued in prepare() and assemble().
        """
        if self.__batch_prepare_assemble:
            raise ElementError("{}: Command batching for prepare/assemble is already configured".format(self))

        self.__batch_prepare_assemble = True
        self.__batch_prepare_assemble_flags = flags
        self.__batch_prepare_assemble_collect = collect

    def get_logs(self) -> List[str]:
        """Obtain a list of log file paths

        Returns:
           A list of log file paths
        """
        return cast(Artifact, self.__artifact).get_logs()

    #############################################################
    #            Private Methods used in BuildStream            #
    #############################################################

    # _dependencies()
    #
    # A generator function which yields the dependencies of the given element.
    #
    # If `recurse` is specified (the default), the full dependencies will be listed
    # in deterministic staging order, starting with the basemost elements in the
    # given `scope`. Otherwise, if `recurse` is not specified then only the direct
    # dependencies in the given `scope` will be traversed, and the element itself
    # will be omitted.
    #
    # Args:
    #    scope (_Scope): The scope to iterate in
    #    recurse (bool): Whether to recurse
    #
    # Yields:
    #    (Element): The dependencies in `scope`, in deterministic staging order
    #
    def _dependencies(self, scope, *, recurse=True, visited=None):

        # The format of visited is (BitMap(), BitMap()), with the first BitMap
        # containing element that have been visited for the `_Scope.BUILD` case
        # and the second one relating to the `_Scope.RUN` case.
        if not recurse:
            result: Set[Element] = set()
            if scope in (_Scope.BUILD, _Scope.ALL):
                for dep in self.__build_dependencies:
                    if dep not in result:
                        result.add(dep)
                        yield dep
            if scope in (_Scope.RUN, _Scope.ALL):
                for dep in self.__runtime_dependencies:
                    if dep not in result:
                        result.add(dep)
                        yield dep
        else:

            def visit(element, scope, visited):
                if scope == _Scope.ALL:
                    visited[0].add(element._unique_id)
                    visited[1].add(element._unique_id)

                    for dep in chain(element.__build_dependencies, element.__runtime_dependencies):
                        if dep._unique_id not in visited[0] and dep._unique_id not in visited[1]:
                            yield from visit(dep, _Scope.ALL, visited)

                    yield element
                elif scope == _Scope.BUILD:
                    visited[0].add(element._unique_id)

                    for dep in element.__build_dependencies:
                        if dep._unique_id not in visited[1]:
                            yield from visit(dep, _Scope.RUN, visited)

                elif scope == _Scope.RUN:
                    visited[1].add(element._unique_id)

                    for dep in element.__runtime_dependencies:
                        if dep._unique_id not in visited[1]:
                            yield from visit(dep, _Scope.RUN, visited)

                    yield element
                else:
                    yield element

            if visited is None:
                # Visited is of the form (Visited for _Scope.BUILD, Visited for _Scope.RUN)
                visited = (BitMap(), BitMap())
            else:
                # We have already a visited set passed. we might be able to short-circuit
                if scope in (_Scope.BUILD, _Scope.ALL) and self._unique_id in visited[0]:
                    return
                if scope in (_Scope.RUN, _Scope.ALL) and self._unique_id in visited[1]:
                    return

            yield from visit(self, scope, visited)

    # _search()
    #
    # Search for a dependency by name
    #
    # Args:
    #    scope (_Scope): The scope to search
    #    name (str): The dependency to search for
    #
    # Returns:
    #    (Element): The dependency element, or None if not found.
    #
    def _search(self, scope, name):

        for dep in self._dependencies(scope):
            if dep.name == name:
                return dep

        return None

    # _stage_artifact()
    #
    # Stage this element's output artifact in the sandbox
    #
    # This will stage the files from the artifact to the sandbox at specified location.
    # The files are selected for staging according to the `include`, `exclude` and `orphans`
    # parameters; if `include` is not specified then all files spoken for by any domain
    # are included unless explicitly excluded with an `exclude` domain.
    #
    # Args:
    #    sandbox: The build sandbox
    #    path: An optional sandbox relative path
    #    action (OverlapAction): The action to take when overlapping with previous invocations
    #    include: An optional list of domains to include files from
    #    exclude: An optional list of domains to exclude files from
    #    orphans: Whether to include files not spoken for by split domains
    #    owner: The session element currently running Element.stage()
    #
    # Raises:
    #    (:class:`.ElementError`): If the element has not yet produced an artifact.
    #
    # Returns:
    #    The result describing what happened while staging
    #
    def _stage_artifact(
        self,
        sandbox: "Sandbox",
        *,
        path: str = None,
        action: str = OverlapAction.WARNING,
        include: Optional[List[str]] = None,
        exclude: Optional[List[str]] = None,
        orphans: bool = True,
        owner: Optional["Element"] = None,
    ) -> FileListResult:

        owner = owner or self
        assert owner._overlap_collector is not None, "Attempted to stage artifacts outside of Element.stage()"

        if not self._cached():
            detail = (
                "No artifacts have been cached yet for that element\n"
                + "Try building the element first with `bst build`\n"
            )
            raise ElementError("No artifacts to stage", detail=detail, reason="uncached-checkout-attempt")

        # Time to use the artifact, check once more that it's there
        self.__assert_cached()

        self.status("Staging {}/{}".format(self.name, self._get_display_key().brief))
        # Disable type checking since we can't easily tell mypy that
        # `self.__artifact` can't be None at this stage.
        files_vdir = self.__artifact.get_files()  # type: ignore

        # Hard link it into the staging area
        #
        vbasedir = sandbox.get_virtual_directory()
        vstagedir = vbasedir if path is None else vbasedir.descend(*path.lstrip(os.sep).split(os.sep), create=True)

        split_filter = self.__split_filter_func(include, exclude, orphans)

        result = vstagedir.import_files(files_vdir, filter_callback=split_filter, report_written=True, can_link=True)

        owner._overlap_collector.collect_stage_result(self, result)

        return result

    # _stage_dependency_artifacts()
    #
    # Stage element dependencies in scope, this is used for core
    # functionality especially in the CLI which wants to stage specifically
    # build or runtime dependencies.
    #
    # Args:
    #    sandbox: The build sandbox
    #    scope (_Scope): The scope of artifacts to stage
    #    path An optional sandbox relative path
    #    include: An optional list of domains to include files from
    #    exclude: An optional list of domains to exclude files from
    #    orphans: Whether to include files not spoken for by split domains
    #
    # Raises:
    #    (:class:`.ElementError`): If any of the dependencies in `scope` have not
    #                              yet produced artifacts, or if forbidden overlaps
    #                              occur.
    #
    def _stage_dependency_artifacts(self, sandbox, scope, *, path=None, include=None, exclude=None, orphans=True):
        with self._overlap_collector.session(OverlapAction.WARNING, path):
            for dep in self._dependencies(scope):
                dep._stage_artifact(sandbox, path=path, include=include, exclude=exclude, orphans=orphans, owner=self)

    # _new_from_load_element():
    #
    # Recursively instantiate a new Element instance, its sources
    # and its dependencies from a LoadElement.
    #
    # FIXME: Need to use an iterative algorithm here since recursion
    #        will limit project dependency depth.
    #
    # Args:
    #    load_element (LoadElement): The LoadElement
    #    task (Task): A task object to report progress to
    #
    # Returns:
    #    (Element): A newly created Element instance
    #
    @classmethod
    def _new_from_load_element(cls, load_element, task=None):

        if not load_element.first_pass:
            load_element.project.ensure_fully_loaded()

        with suppress(KeyError):
            return cls.__instantiated_elements[load_element]

        element = load_element.project.create_element(load_element)
        cls.__instantiated_elements[load_element] = element

        # If the element implements configure_dependencies(), we will collect
        # the dependency configurations for it, otherwise we will consider
        # it an error to specify `config` on dependencies.
        #
        if element.configure_dependencies.__func__ is not Element.configure_dependencies:
            custom_configurations = []
        else:
            custom_configurations = None

        # Load the sources from the LoadElement
        element.__load_sources(load_element)

        # Instantiate dependencies
        for dep in load_element.dependencies:
            dependency = Element._new_from_load_element(dep.element, task)

            if dep.dep_type & DependencyType.BUILD:
                element.__build_dependencies.append(dependency)
                dependency.__reverse_build_deps.add(element)

                # Configuration data is only collected for build dependencies,
                # if configuration data is specified on a runtime dependency
                # then the assertion will be raised by the LoadElement.
                #
                if custom_configurations is not None:

                    # Create a proxy for the dependency
                    dep_proxy = cast("Element", ElementProxy(element, dependency))

                    # Class supports dependency configuration
                    if dep.config_nodes:

                        # Ensure variables are substituted first
                        #
                        for config in dep.config_nodes:
                            element.__variables.expand(config)

                        custom_configurations.extend(
                            [DependencyConfiguration(dep_proxy, dep.path, config) for config in dep.config_nodes]
                        )
                    else:
                        custom_configurations.append(DependencyConfiguration(dep_proxy, dep.path, None))

                elif dep.config_nodes:
                    # Class does not support dependency configuration
                    provenance = dep.config_nodes[0].get_provenance()
                    raise LoadError(
                        "{}: Custom dependency configuration is not supported by element plugin '{}'".format(
                            provenance, element.get_kind()
                        ),
                        LoadErrorReason.INVALID_DEPENDENCY_CONFIG,
                    )

            if dep.dep_type & DependencyType.RUNTIME:
                element.__runtime_dependencies.append(dependency)
                dependency.__reverse_runtime_deps.add(element)

            if dep.strict:
                element.__strict_dependencies.append(dependency)

        no_of_runtime_deps = len(element.__runtime_dependencies)
        element.__runtime_deps_uncached = no_of_runtime_deps

        no_of_build_deps = len(element.__build_dependencies)
        element.__build_deps_uncached = no_of_build_deps

        if custom_configurations is not None:
            element.configure_dependencies(custom_configurations)

        element.__preflight()

        if task:
            task.add_current_progress()

        return element

    # _clear_meta_elements_cache()
    #
    # Clear the internal meta elements cache.
    #
    # When loading elements from meta, we cache already instantiated elements
    # in order to not have to load the same elements twice.
    # This clears the cache.
    #
    # It should be called whenever we are done loading all elements in order
    # to save memory.
    #
    @classmethod
    def _clear_meta_elements_cache(cls):
        cls.__instantiated_elements = {}

    # _get_redundant_source_refs()
    #
    # Fetches a list of (Source, ref) tuples of all the Sources
    # which were loaded with a ref specified in the element declaration
    # for projects which use project.refs ref-storage.
    #
    # This is used to produce a warning
    @classmethod
    def _get_redundant_source_refs(cls):
        return cls.__redundant_source_refs

    # _reset_load_state()
    #
    # This is used to reset the loader state across multiple load sessions.
    #
    @classmethod
    def _reset_load_state(cls):
        cls.__instantiated_elements = {}
        cls.__redundant_source_refs = []

    # _cached():
    #
    # Returns:
    #    (bool): Whether this element is already present in
    #            the artifact cache
    #
    def _cached(self):
        if not self.__artifact:
            return False

        return self.__artifact.cached()

    # _cached_remotely():
    #
    # Returns:
    #    (bool): Whether this element is present in a remote cache
    #
    def _cached_remotely(self):
        if self.__cached_remotely is None:
            self.__cached_remotely = self.__artifacts.check_remotes_for_element(self)
        return self.__cached_remotely

    # _get_build_result():
    #
    # Returns:
    #    (bool): Whether the artifact of this element present in the artifact cache is of a success
    #    (str): Short description of the result
    #    (str): Detailed description of the result
    #
    def _get_build_result(self):
        if self.__build_result is None:
            self.__load_build_result()

        return self.__build_result

    # __set_build_result():
    #
    # Sets the assembly result
    #
    # Args:
    #    success (bool): Whether the result is a success
    #    description (str): Short description of the result
    #    detail (str): Detailed description of the result
    #
    def __set_build_result(self, success, description, detail=None):
        self.__build_result = (success, description, detail)

    # _set_public_data():
    #
    # Set public data on this element
    #
    # Args:
    #    domain: A public domain name to fetch data for
    #    data: The public data dictionary for the given domain
    #
    # This internal function allows the core and core components to doctor
    # the public data after being loaded, as the filter element does for instance
    # in order to propagate some public data from it's dependency forward to itself.
    #
    def _set_public_data(self, domain: str, data: "MappingNode[Node]") -> None:
        self.__public[domain] = data.clone()  # type: ignore

    # _cached_success():
    #
    # Returns:
    #    (bool): Whether this element is already present in
    #            the artifact cache and the element assembled successfully
    #
    def _cached_success(self):
        # FIXME:  _cache() and _cached_success() should be converted to
        # push based functions where we only update __cached_successfully
        # once we know this has changed. This will allow us to cheaply check
        # __cached_successfully instead of calling _cached_success()
        if self.__cached_successfully:
            return True

        if not self._cached():
            return False

        success, _, _ = self._get_build_result()
        if success:
            self.__cached_successfully = True
            return True
        else:
            return False

    # _cached_failure():
    #
    # Returns:
    #    (bool): Whether this element is already present in
    #            the artifact cache and the element did not assemble successfully
    #
    def _cached_failure(self):
        if not self._cached():
            return False

        success, _, _ = self._get_build_result()
        return not success

    # _buildable():
    #
    # Returns:
    #    (bool): Whether this element can currently be built
    #
    def _buildable(self):
        if self._fetch_needed():
            return False

        if not self.__assemble_scheduled:
            return False

        return self.__build_deps_uncached == 0

    # _get_cache_key():
    #
    # Returns the cache key
    #
    # Args:
    #    strength (_KeyStrength): Either STRONG or WEAK key strength
    #
    # Returns:
    #    (str): A hex digest cache key for this Element, or None
    #
    # None is returned if information for the cache key is missing.
    #
    def _get_cache_key(self, strength=_KeyStrength.STRONG):
        if strength == _KeyStrength.STRONG:
            return self.__cache_key
        else:
            return self.__weak_cache_key

    # _can_query_cache():
    #
    # Returns whether the cache key required for cache queries is available.
    #
    # Returns:
    #    (bool): True if cache can be queried
    #
    def _can_query_cache(self):
        # cache cannot be queried until strict cache key is available
        return self.__strict_cache_key is not None

    # _initialize_state()
    #
    # Compute up the elment's initial state. Element state contains
    # the following mutable sub-states:
    #
    # - Source state in `ElementSources`
    # - Artifact cache key
    #   - Source key in `ElementSources`
    #     - Integral component of the cache key
    #     - Computed as part of the source state
    # - Artifact state
    #   - Cache key
    #     - Must be known to compute this state
    # - Build status
    #   - Artifact state
    #     - Must be known before we can decide whether to build
    #
    # Note that sub-states are dependent on each other, and changes to
    # one state will effect changes in the next.
    #
    # Changes to these states can be caused by numerous things,
    # notably jobs executed in sub-processes. Changes are performed by
    # invocations of the following methods:
    #
    # - __update_cache_keys()
    #   - Computes the strong and weak cache keys.
    # - _update_artifact_state()
    #   - Computes the state of the element's artifact using the
    #     cache key.
    # - __schedule_assembly_when_necessary()
    #   - Schedules assembly of an element, iff its current state
    #     allows/necessitates it
    # - __update_cache_key_non_strict()
    #   - Sets strict cache keys in non-strict builds
    #     - Some non-strict build actions can create artifacts
    #       compatible with strict mode (such as pulling), so
    #       this needs to be done
    #
    # When any one of these methods are called and cause a change,
    # they will invoke methods that have a potential dependency on
    # them, causing the state change to bubble through all potential
    # side effects.
    #
    # After initializing the source state via `ElementSources`,
    # *this* method starts the process by invoking
    # `__update_cache_keys()`, which will cause all necessary state
    # changes. Other functions should use the appropriate methods and
    # only update what they expect to change - this will ensure that
    # the minimum amount of work is done.
    #
    def _initialize_state(self):
        if self.__resolved_initial_state:
            return
        self.__resolved_initial_state = True

        # This will initialize source state.
        self.__sources.update_resolved_state()

        # This will calculate the cache keys, and for un-initialized
        # elements recursively initialize anything else (because it
        # will become considered outdated after cache keys are
        # updated).
        self.__update_cache_keys()

    # _get_display_key():
    #
    # Returns cache keys for display purposes
    #
    # Returns:
    #    (_DisplayKey): The display key
    #
    # Question marks are returned if information for the cache key is missing.
    #
    def _get_display_key(self):
        context = self._get_context()
        strict = False

        cache_key = self._get_cache_key()

        if not cache_key:
            cache_key = "{:?<64}".format("")
        elif cache_key == self.__strict_cache_key:
            # Strong cache key used in this session matches cache key
            # that would be used in strict build mode
            strict = True

        length = min(len(cache_key), context.log_key_length)
        return _DisplayKey(cache_key, cache_key[0:length], strict)

    # _tracking_done():
    #
    # This is called in the main process after the element has been tracked
    #
    def _tracking_done(self):
        # Tracking may change the sources' refs, and therefore the
        # source state. We need to update source state.
        self.__sources.update_resolved_state()
        self.__update_cache_keys()

    # _track():
    #
    # Calls track() on the Element sources
    #
    # Raises:
    #    SourceError: If one of the element sources has an error
    #
    # Returns:
    #    (list): A list of Source object ids and their new references
    #
    def _track(self):
        return self.__sources.track(self._get_workspace())

    # _prepare_sandbox():
    #
    # This stages things for either _shell() (below) or also
    # is used to stage things by the `bst artifact checkout` codepath
    #
    @contextmanager
    def _prepare_sandbox(self, scope, shell=False, integrate=True, usebuildtree=False):

        # Assert first that we have a sandbox configuration
        if not self.__sandbox_config:
            raise ElementError(
                "Error preparing sandbox for element: {}".format(self.name),
                detail="This is most likely an artifact that is not yet cached, try building or pulling the artifact first",
                reason="missing-sandbox-config",
            )

        # bst shell and bst artifact checkout require a local sandbox.
        with self.__sandbox(None, config=self.__sandbox_config, allow_remote=False) as sandbox:
            sandbox._usebuildtree = usebuildtree

            # Configure always comes first, and we need it.
            self.__configure_sandbox(sandbox)

            # Stage what we need
            if shell and scope == _Scope.BUILD:
                self.__stage(sandbox)
            else:
                # Stage deps in the sandbox root
                with self.timed_activity("Staging dependencies", silent_nested=True), self.__collect_overlaps():
                    self._stage_dependency_artifacts(sandbox, scope)

                # Run any integration commands provided by the dependencies
                # once they are all staged and ready
                if integrate:
                    with self.timed_activity("Integrating sandbox"):
                        for dep in self._dependencies(scope):
                            dep.integrate(sandbox)

            yield sandbox

    # _stage_sources_in_sandbox():
    #
    # Stage this element's sources to a directory inside sandbox
    #
    # Args:
    #     sandbox (:class:`.Sandbox`): The build sandbox
    #     directory (str): An absolute path to stage the sources at
    #
    def _stage_sources_in_sandbox(self, sandbox, directory):

        # Stage all sources that need to be copied
        sandbox_vroot = sandbox.get_virtual_directory()
        host_vdirectory = sandbox_vroot.descend(*directory.lstrip(os.sep).split(os.sep), create=True)
        self._stage_sources_at(host_vdirectory, usebuildtree=sandbox._usebuildtree)

    # _stage_sources_at():
    #
    # Stage this element's sources to a directory
    #
    # Args:
    #     vdirectory (:class:`.storage.Directory`): A virtual directory object to stage sources into.
    #     usebuildtree (bool): use a the elements build tree as its source.
    #
    def _stage_sources_at(self, vdirectory, usebuildtree=False):

        # It's advantageous to have this temporary directory on
        # the same file system as the rest of our cache.
        with self.timed_activity("Staging sources", silent_nested=True):

            if not isinstance(vdirectory, Directory):
                vdirectory = FileBasedDirectory(vdirectory)
            if not vdirectory.is_empty():
                raise ElementError("Staging directory '{}' is not empty".format(vdirectory))

            # Check if we have a cached buildtree to use
            if usebuildtree:
                import_dir = self.__artifact.get_buildtree()
                if import_dir.is_empty():
                    detail = "Element type either does not expect a buildtree or it was explictily cached without one."
                    self.warn("WARNING: {} Artifact contains an empty buildtree".format(self.name), detail=detail)

            # No cached buildtree, stage source from source cache
            else:
                staged_sources = self.__sources.get_files()

                # incremental builds should merge the source into the last artifact before staging
                last_build_artifact = self.__get_last_build_artifact()
                if last_build_artifact:
                    self.info("Incremental build")
                    last_sources = last_build_artifact.get_sources()
                    import_dir = last_build_artifact.get_buildtree()
                    import_dir._apply_changes(last_sources, staged_sources)
                else:
                    import_dir = staged_sources

            # Set update_mtime to ensure deterministic mtime of sources at build time
            vdirectory.import_files(import_dir, update_mtime=BST_ARBITRARY_TIMESTAMP)

        # Ensure deterministic owners of sources at build time
        vdirectory.set_deterministic_user()

    # _set_required():
    #
    # Mark this element and its dependencies as required.
    # This unblocks pull/fetch/build.
    #
    # Args:
    #    scope (_Scope): The scope of dependencies to mark as required
    #
    def _set_required(self, scope=_Scope.RUN):
        assert utils._is_in_main_thread(), "This has an impact on all elements and must be run in the main thread"

        if self.__required:
            # Already done
            return

        self.__required = True

        # Request artifacts of dependencies
        for dep in self._dependencies(scope, recurse=False):
            dep._set_required(scope=_Scope.RUN)

        # When an element becomes required, it must be assembled for
        # the current pipeline. `__schedule_assembly_when_necessary()`
        # will abort if some other state prevents it from being built,
        # and changes to such states will cause re-scheduling, so this
        # is safe.
        self.__schedule_assembly_when_necessary()

        # Callback to the Queue
        if self.__required_callback is not None:
            self.__required_callback(self)
            self.__required_callback = None

    # _is_required():
    #
    # Returns whether this element has been marked as required.
    #
    def _is_required(self):
        return self.__required

    # _set_artifact_files_required():
    #
    # Mark artifact files for this element and its runtime dependencies as
    # required in the local cache.
    #
    def _set_artifact_files_required(self, scope=_Scope.RUN):
        assert utils._is_in_main_thread(), "This has an impact on all elements and must be run in the main thread"

        if self.__artifact_files_required:
            # Already done
            return

        self.__artifact_files_required = True

        # Request artifact files of runtime dependencies
        for dep in self._dependencies(scope, recurse=False):
            dep._set_artifact_files_required(scope=scope)

    # _artifact_files_required():
    #
    # Returns whether artifact files for this element have been marked as required.
    #
    def _artifact_files_required(self):
        return self.__artifact_files_required

    # __should_schedule()
    #
    # Returns:
    #     bool - Whether the element can be scheduled for a build.
    #
    def __should_schedule(self):
        # We're processing if we're already scheduled, we've
        # finished assembling or if we're waiting to pull.
        processing = self.__assemble_scheduled or self.__assemble_done or self._pull_pending()

        # We should schedule a build when
        return (
            # We're not processing
            not processing
            and
            # We're required for the current build
            self._is_required()
            and
            # We have figured out the state of our artifact
            self.__artifact
            and
            # And we're not cached yet
            not self._cached_success()
        )

    # __schedule_assembly_when_necessary():
    #
    # This is called in the main process before the element is assembled
    # in a subprocess.
    #
    def __schedule_assembly_when_necessary(self):
        assert utils._is_in_main_thread(), "This has an impact on all elements and must be run in the main thread"

        # FIXME: We could reduce the number of function calls a bit by
        # factoring this out of this method (and checking whether we
        # should schedule at the calling end).
        #
        # This would make the code less pretty, but it's a possible
        # optimization if we get desperate enough (and we will ;)).
        if not self.__should_schedule():
            return

        self.__assemble_scheduled = True

        # Requests artifacts of build dependencies
        for dep in self._dependencies(_Scope.BUILD, recurse=False):
            dep._set_required()

        # Once we schedule an element for assembly, we know that our
        # build dependencies have strong cache keys, so we can update
        # our own strong cache key.
        self.__update_cache_key_non_strict()

    # _assemble_done():
    #
    # This is called in the main process after the element has been assembled.
    #
    # This will result in updating the element state.
    #
    # Args:
    #     successful (bool): Whether the build was successful
    #
    def _assemble_done(self, successful):
        assert self.__assemble_scheduled
        assert utils._is_in_main_thread(), "This has an impact on all elements and must be run in the main thread"

        self.__assemble_done = True

        if successful:
            # Directly set known cached status as optimization to avoid
            # querying buildbox-casd and the filesystem.
            self.__artifact.set_cached()
            self.__cached_successfully = True
        else:
            self.__artifact.reset_cached()

        # When we're building in non-strict mode, we may have
        # assembled everything to this point without a strong cache
        # key. Once the element has been assembled, a strong cache key
        # can be set, so we do so.
        self.__update_cache_key_non_strict()
        self._update_ready_for_runtime_and_cached()

        if self._get_workspace() and self._cached():
            # Note that this block can only happen in the
            # main process, since `self._cached_success()` cannot
            # be true when assembly is successful in the task.
            #
            # For this reason, it is safe to update and
            # save the workspaces configuration
            #
            key = self._get_cache_key()
            workspace = self._get_workspace()
            workspace.last_build = key
            self._get_context().get_workspaces().save_config()

    # _assemble():
    #
    # Internal method for running the entire build phase.
    #
    # This will:
    #   - Prepare a sandbox for the build
    #   - Call the public abstract methods for the build phase
    #   - Cache the resulting artifact
    #
    # Returns:
    #    (int): The size of the newly cached artifact
    #
    def _assemble(self):

        # Only do this the first time around (i.e. __assemble_done is False)
        # to allow for retrying the job
        if self._cached_failure() and not self.__assemble_done:
            with self._output_file() as output_file:
                for log_path in self.__artifact.get_logs():
                    with open(log_path) as log_file:
                        output_file.write(log_file.read())

            _, description, detail = self._get_build_result()
            e = CachedFailure(description, detail=detail)
            # Shelling into a sandbox is useful to debug this error
            e.sandbox = True
            raise e

        # Assert call ordering
        assert not self._cached_success()

        # Print the environment at the beginning of the log file.
        env_dump = yaml.round_trip_dump(self.get_environment(), default_flow_style=False, allow_unicode=True)
        self.log("Build environment for element {}".format(self.name), detail=env_dump)

        context = self._get_context()
        with self._output_file() as output_file:

            # Explicitly clean it up, keep the build dir around if exceptions are raised
            os.makedirs(context.builddir, exist_ok=True)

            with utils._tempdir(
                prefix="{}-".format(self.normal_name), dir=context.builddir
            ) as rootdir, self.__sandbox(
                rootdir, output_file, output_file, self.__sandbox_config
            ) as sandbox:  # noqa

                # Let the sandbox know whether the buildtree will be required.
                # This allows the remote execution sandbox to skip buildtree
                # download when it's not needed.
                buildroot = self.get_variable("build-root")
                cache_buildtrees = context.cache_buildtrees
                if cache_buildtrees != _CacheBuildTrees.NEVER:
                    always_cache_buildtrees = cache_buildtrees == _CacheBuildTrees.ALWAYS
                    sandbox._set_build_directory(buildroot, always=always_cache_buildtrees)

                if not self.BST_RUN_COMMANDS:
                    # Element doesn't need to run any commands in the sandbox.
                    #
                    # Disable Sandbox.run() to allow CasBasedDirectory for all
                    # sandboxes.
                    sandbox._disable_run()

                # Call the abstract plugin methods

                # Step 1 - Configure
                self.__configure_sandbox(sandbox)
                # Step 2 - Stage
                self.__stage(sandbox)
                try:
                    if self.__batch_prepare_assemble:
                        cm = sandbox.batch(
                            self.__batch_prepare_assemble_flags, collect=self.__batch_prepare_assemble_collect
                        )
                    else:
                        cm = contextlib.suppress()

                    with cm:
                        # Step 3 - Prepare
                        self.__prepare(sandbox)
                        # Step 4 - Assemble
                        collect = self.assemble(sandbox)  # pylint: disable=assignment-from-no-return

                    self.__set_build_result(success=True, description="succeeded")
                except (ElementError, SandboxCommandError) as e:
                    # Shelling into a sandbox is useful to debug this error
                    e.sandbox = True

                    self.__set_build_result(success=False, description=str(e), detail=e.detail)
                    self._cache_artifact(sandbox, e.collect)

                    raise
                else:
                    return self._cache_artifact(sandbox, collect)

    def _cache_artifact(self, sandbox, collect):

        context = self._get_context()
        buildresult = self.__build_result
        publicdata = self.__public
        sandbox_vroot = sandbox.get_virtual_directory()
        collectvdir = None
        sandbox_build_dir = None
        sourcesvdir = None

        cache_buildtrees = context.cache_buildtrees
        build_success = buildresult[0]

        # cache_buildtrees defaults to 'auto', only caching buildtrees
        # when necessary, which includes failed builds.
        # If only caching failed artifact buildtrees, then query the build
        # result. Element types without a build-root dir will be cached
        # with an empty buildtreedir regardless of this configuration.

        if cache_buildtrees == _CacheBuildTrees.ALWAYS or (
            cache_buildtrees == _CacheBuildTrees.AUTO and (not build_success or self._get_workspace())
        ):
            try:
                sandbox_build_dir = sandbox_vroot.descend(
                    *self.get_variable("build-root").lstrip(os.sep).split(os.sep)
                )
                sandbox._fetch_missing_blobs(sandbox_build_dir)
            except VirtualDirectoryError:
                # Directory could not be found. Pre-virtual
                # directory behaviour was to continue silently
                # if the directory could not be found.
                pass

            sourcesvdir = self.__sources.get_files()

        if collect is not None:
            try:
                collectvdir = sandbox_vroot.descend(*collect.lstrip(os.sep).split(os.sep))
                sandbox._fetch_missing_blobs(collectvdir)
            except VirtualDirectoryError:
                pass

        # We should always have cache keys already set when caching an artifact
        assert self.__cache_key is not None
        assert self.__artifact._cache_key is not None

        with self.timed_activity("Caching artifact"):
            artifact_size = self.__artifact.cache(
                sandbox_build_dir=sandbox_build_dir,
                collectvdir=collectvdir,
                sourcesvdir=sourcesvdir,
                buildresult=buildresult,
                publicdata=publicdata,
                variables=self.__variables,
                environment=self.__environment,
                sandboxconfig=self.__sandbox_config,
            )

        if collect is not None and collectvdir is None:
            raise ElementError(
                "Directory '{}' was not found inside the sandbox, "
                "unable to collect artifact contents".format(collect)
            )

        return artifact_size

    # _fetch_done()
    #
    # Indicates that fetching the sources for this element has been done.
    #
    # Args:
    #   fetched_original (bool): Whether the original sources had been asked (and fetched) or not
    #
    def _fetch_done(self, fetched_original):
        assert utils._is_in_main_thread(), "This has an impact on all elements and must be run in the main thread"

        self.__sources.fetch_done(fetched_original)

    # _pull_pending()
    #
    # Check whether the artifact will be pulled. If the pull operation is to
    # include a specific subdir of the element artifact (from cli or user conf)
    # then the local cache is queried for the subdirs existence.
    #
    # Returns:
    #   (bool): Whether a pull operation is pending
    #
    def _pull_pending(self):
        if self._get_workspace():
            # Workspace builds are never pushed to artifact servers
            return False

        # Check whether the pull has been invoked with a specific subdir requested
        # in user context, as to complete a partial artifact
        pull_buildtrees = self._get_context().pull_buildtrees

        if self._cached() and self.__artifact._cache_key == self.__strict_cache_key:
            if pull_buildtrees:
                # If we've specified a subdir, check if the subdir is cached locally
                # or if it's possible to get
                if self._cached_buildtree() or not self._buildtree_exists():
                    return False
            else:
                return False

        # Pull is pending if artifact remote server available
        # and pull has not been attempted yet
        return self.__artifacts.has_fetch_remotes(plugin=self) and not self.__pull_done

    # _pull_done()
    #
    # Indicate that pull was attempted.
    #
    # This needs to be called in the main process after a pull
    # succeeds or fails so that we properly update the main
    # process data model
    #
    # This will result in updating the element state.
    #
    def _pull_done(self):
        assert utils._is_in_main_thread(), "This has an impact on all elements and must be run in the main thread"

        self.__pull_done = True

        # Artifact may become cached after pulling, so let it query the
        # filesystem again to check
        self.__artifact.reset_cached()

        # We may not have actually pulled an artifact - the pull may
        # have failed. We might therefore need to schedule assembly.
        self.__schedule_assembly_when_necessary()
        # If we've finished pulling, an artifact might now exist
        # locally, so we might need to update a non-strict strong
        # cache key.
        self.__update_cache_key_non_strict()
        self._update_ready_for_runtime_and_cached()

    # _pull():
    #
    # Pull artifact from remote artifact repository into local artifact cache.
    #
    # Returns: True if the artifact has been downloaded, False otherwise
    #
    def _pull(self):
        context = self._get_context()

        # Get optional specific subdir to pull and optional list to not pull
        # based off of user context
        pull_buildtrees = context.pull_buildtrees

        # Attempt to pull artifact without knowing whether it's available
        strict_artifact = Artifact(self, context, strong_key=self.__strict_cache_key, weak_key=self.__weak_cache_key)
        if strict_artifact.pull(pull_buildtrees=pull_buildtrees):
            # Notify successful download
            return True

        if not context.get_strict() and not self._cached():
            # In non-strict mode also try pulling weak artifact
            # if no weak artifact is cached yet.
            artifact = Artifact(self, context, weak_key=self.__weak_cache_key)
            return artifact.pull(pull_buildtrees=pull_buildtrees)
        else:
            # No artifact has been downloaded
            return False

    def _skip_source_push(self):
        if not self.sources() or self._get_workspace():
            return True
        return not (self.__sourcecache.has_push_remotes(plugin=self) and self._cached_sources())

    def _source_push(self):
        return self.__sources.push()

    # _skip_push():
    #
    # Determine whether we should create a push job for this element.
    #
    # Args:
    #    skip_uncached (bool): Whether to skip elements that aren't cached
    #
    # Returns:
    #   (bool): True if this element does not need a push job to be created
    #
    def _skip_push(self, *, skip_uncached):
        if not self.__artifacts.has_push_remotes(plugin=self):
            # No push remotes for this element's project
            return True

        # Do not push elements that aren't cached, or that are cached with a dangling buildtree
        # ref unless element type is expected to have an an empty buildtree directory
        if skip_uncached:
            if not self._cached():
                return True
            if not self._cached_buildtree() and self._buildtree_exists():
                return True

        return False

    # _push():
    #
    # Push locally cached artifact to remote artifact repository.
    #
    # Returns:
    #   (bool): True if the remote was updated, False if it already existed
    #           and no updated was required
    #
    def _push(self):
        if not self._cached():
            raise ElementError("Push failed: {} is not cached".format(self.name))

        # Do not push elements that are cached with a dangling buildtree ref
        # unless element type is expected to have an an empty buildtree directory
        if not self._cached_buildtree() and self._buildtree_exists():
            raise ElementError("Push failed: buildtree of {} is not cached".format(self.name))

        if self.__get_tainted():
            self.warn("Not pushing tainted artifact.")
            return False

        # Push all keys used for local commit via the Artifact member
        pushed = self.__artifacts.push(self, self.__artifact)
        if not pushed:
            return False

        # Notify successful upload
        return True

    # _shell():
    #
    # Connects the terminal with a shell running in a staged
    # environment
    #
    # Args:
    #    scope (_Scope): Either BUILD or RUN scopes are valid, or None
    #    mounts (list): A list of (str, str) tuples, representing host/target paths to mount
    #    isolate (bool): Whether to isolate the environment like we do in builds
    #    prompt (str): A suitable prompt string for PS1
    #    command (list): An argv to launch in the sandbox
    #    usebuildtree (bool): Use the buildtree as its source
    #
    # Returns: Exit code
    def _shell(self, scope=None, *, mounts=None, isolate=False, prompt=None, command=None, usebuildtree=False):

        with self._prepare_sandbox(scope, shell=True, usebuildtree=usebuildtree) as sandbox:
            environment = self.get_environment()
            environment = copy.copy(environment)
            flags = SandboxFlags.INTERACTIVE | SandboxFlags.ROOT_READ_ONLY

            # Fetch the main toplevel project, in case this is a junctioned
            # subproject, we want to use the rules defined by the main one.
            context = self._get_context()
            project = context.get_toplevel_project()
            shell_command, shell_environment, shell_host_files = project.get_shell_config()

            if prompt is not None:
                environment["PS1"] = prompt

            # Special configurations for non-isolated sandboxes
            if not isolate:

                # Open the network, and reuse calling uid/gid
                #
                flags |= SandboxFlags.NETWORK_ENABLED | SandboxFlags.INHERIT_UID

                # Apply project defined environment vars to set for a shell
                for key, value in shell_environment.items():
                    environment[key] = value

                # Setup any requested bind mounts
                if mounts is None:
                    mounts = []

                for mount in shell_host_files + mounts:
                    if not os.path.exists(mount.host_path):
                        if not mount.optional:
                            self.warn("Not mounting non-existing host file: {}".format(mount.host_path))
                    else:
                        sandbox.mark_directory(mount.path)
                        sandbox._set_mount_source(mount.path, mount.host_path)

            if command:
                argv = command
            else:
                argv = shell_command

            self.status("Running command", detail=" ".join(argv))

            # Run shells with network enabled and readonly root.
            return sandbox.run(argv, flags, env=environment)

    # _open_workspace():
    #
    # "Open" a workspace for this element
    #
    # This requires that a workspace already be created in
    # the workspaces metadata first.
    #
    def _open_workspace(self):
        assert utils._is_in_main_thread(), "This writes to a global file and therefore must be run in the main thread"

        context = self._get_context()
        workspace = self._get_workspace()
        assert workspace is not None

        # First lets get a temp dir in our build directory
        # and stage there, then link the files over to the desired
        # path.
        #
        # We do this so that force opening workspaces which overwrites
        # files in the target directory actually works without any
        # additional support from Source implementations.
        #
        os.makedirs(context.builddir, exist_ok=True)
        with utils._tempdir(dir=context.builddir, prefix="workspace-{}".format(self.normal_name)) as temp:
            self.__sources.init_workspace(temp)

            # Now hardlink the files into the workspace target.
            utils.link_files(temp, workspace.get_absolute_path())

    # _get_workspace():
    #
    # Returns:
    #    (Workspace|None): A workspace associated with this element
    #
    def _get_workspace(self):
        workspaces = self._get_context().get_workspaces()
        return workspaces.get_workspace(self._get_full_name())

    # _write_script():
    #
    # Writes a script to the given directory.
    def _write_script(self, directory):
        with open(_site.build_module_template, "r") as f:
            script_template = f.read()

        variable_string = ""
        for var, val in self.get_environment().items():
            variable_string += "{0}={1} ".format(var, val)

        script = script_template.format(
            name=self.normal_name,
            build_root=self.get_variable("build-root"),
            install_root=self.get_variable("install-root"),
            variables=variable_string,
            commands=self.generate_script(),
        )

        os.makedirs(directory, exist_ok=True)
        script_path = os.path.join(directory, "build-" + self.normal_name)

        with self.timed_activity("Writing build script", silent_nested=True):
            with utils.save_file_atomic(script_path, "w") as script_file:
                script_file.write(script)

            os.chmod(script_path, stat.S_IEXEC | stat.S_IREAD)

    # Returns the element whose sources this element is ultimately derived from.
    #
    # This is intended for being used to redirect commands that operate on an
    # element to the element whose sources it is ultimately derived from.
    #
    # For example, element A is a build element depending on source foo,
    # element B is a filter element that depends on element A. The source
    # element of B is A, since B depends on A, and A has sources.
    #
    def _get_source_element(self):
        return self

    # _cached_buildtree()
    #
    # Check if element artifact contains expected buildtree. An
    # element's buildtree artifact will not be present if the rest
    # of the partial artifact is not cached.
    #
    # Returns:
    #     (bool): True if artifact cached with buildtree, False if
    #             element not cached or missing expected buildtree.
    #             Note this only confirms if a buildtree is present,
    #             not its contents.
    #
    def _cached_buildtree(self):
        if not self._cached():
            return False

        return self.__artifact.cached_buildtree()

    # _buildtree_exists()
    #
    # Check if artifact was created with a buildtree. This does not check
    # whether the buildtree is present in the local cache.
    #
    # Returns:
    #     (bool): True if artifact was created with buildtree, False if
    #             element not cached or not created with a buildtree.
    #
    def _buildtree_exists(self):
        if not self._cached():
            return False

        return self.__artifact.buildtree_exists()

    # _cached_logs()
    #
    # Check if the artifact is cached with log files.
    #
    # Returns:
    #     (bool): True if artifact is cached with logs, False if
    #             element not cached or missing logs.
    #
    def _cached_logs(self):
        return self.__artifact.cached_logs()

    # _fetch()
    #
    # Fetch the element's sources.
    #
    # Raises:
    #    SourceError: If one of the element sources has an error
    #
    def _fetch(self, fetch_original=False):
        if fetch_original:
            self.__sources.fetch_sources(fetch_original=True)

        self.__sources.fetch()

        if not self.__sources.cached():
            try:
                # Stage all element sources into CAS
                self.__sources.stage_and_cache()
            except (SourceCacheError, VirtualDirectoryError) as e:
                raise ElementError(
                    "Error trying to stage sources for {}: {}".format(self.name, e), reason="stage-sources-fail"
                )

    # _calculate_cache_key():
    #
    # Calculates the cache key
    #
    # Args:
    #    dependencies (List[List[str]]): list of dependencies with project name,
    #                                    element name and optional cache key
    #
    # Returns:
    #    (str): A hex digest cache key for this Element, or None
    #
    # None is returned if information for the cache key is missing.
    #
    def _calculate_cache_key(self, dependencies):
        # No cache keys for dependencies which have no cache keys
        if any(not all(dep) for dep in dependencies):
            return None

        # Generate dict that is used as base for all cache keys
        if self.__cache_key_dict is None:
            # Filter out nocache variables from the element's environment
            cache_env = {key: value for key, value in self.__environment.items() if key not in self.__env_nocache}

            project = self._get_project()

            self.__cache_key_dict = {
                "core-artifact-version": BST_CORE_ARTIFACT_VERSION,
                "element-base-key": self.__get_base_key(),
                "element-plugin-key": self.get_unique_key(),
                "element-plugin-name": self.get_kind(),
                "element-plugin-version": self.BST_ARTIFACT_VERSION,
                "sandbox": self.__sandbox_config.to_dict(),
                "environment": cache_env,
                "public": self.__public.strip_node_info(),
            }

            self.__cache_key_dict["sources"] = self.__sources.get_unique_key()

            self.__cache_key_dict["fatal-warnings"] = sorted(project._fatal_warnings)

        cache_key_dict = self.__cache_key_dict.copy()
        cache_key_dict["dependencies"] = dependencies

        return _cachekey.generate_key(cache_key_dict)

    # _cached_sources()
    #
    # Get whether the staged element sources are cached in CAS
    #
    # Returns:
    #    (bool): True if the element sources are in CAS
    #
    def _cached_sources(self):
        return self.__sources.cached()

    # _has_all_sources_resolved()
    #
    # Get whether all sources of the element are resolved
    #
    # Returns:
    #    (bool): True if all element sources are resolved
    #
    def _has_all_sources_resolved(self):
        return self.__sources.is_resolved()

    # _fetch_needed():
    #
    # Return whether sources need to be fetched from a remote
    #
    # Returns:
    #    (bool): True if one or more element sources need to be fetched
    #
    def _fetch_needed(self):
        return not self.__sources.cached() and not self.__sources.cached_original()

    # _should_fetch():
    #
    # Return whether we need to run the fetch stage for this element
    #
    # Args:
    #    fetch_original (bool): whether we need the original unstaged source
    #
    # Returns:
    #    (bool): True if a fetch job is required
    #
    def _should_fetch(self, fetch_original=False):
        if fetch_original:
            return not self.__sources.cached_original()
        return not self.__sources.cached()

    # _set_required_callback()
    #
    #
    # Notify the pull/fetch/build queue that the element is potentially
    # ready to be processed.
    #
    # _Set the _required_callback - the _required_callback is invoked when an
    # element is marked as required. This informs us that the element needs to
    # either be pulled or fetched + built.
    #
    # Args:
    #    callback (callable) - The callback function
    #
    def _set_required_callback(self, callback):
        self.__required_callback = callback

    # _set_can_query_cache_callback()
    #
    # Notify the pull/fetch queue that the element is potentially
    # ready to be processed.
    #
    # Set the _can_query_cache_callback - the _can_query_cache_callback is
    # invoked when an element becomes able to query the cache. That is,
    # the (non-workspaced) element's strict cache key has been calculated.
    # However, if the element is workspaced, we also invoke this callback
    # once its build has been scheduled - this ensures that the workspaced
    # element does not get blocked in the pull queue.
    #
    # Args:
    #    callback (callable) - The callback function
    #
    def _set_can_query_cache_callback(self, callback):
        self.__can_query_cache_callback = callback

    # _set_buildable_callback()
    #
    # Notifiy the build queue that the element is potentially ready
    # to be processed
    #
    # Set the _buildable_callback - the _buildable_callback is invoked when
    # an element is marked as "buildable". That is, its sources are consistent,
    # its been scheduled to be built and all of its build dependencies have
    # had their cache key's calculated and are cached.
    #
    # Args:
    #    callback (callable) - The callback function
    #
    def _set_buildable_callback(self, callback):
        self.__buildable_callback = callback

    # _set_depth()
    #
    # Set the depth of the Element.
    #
    # The depth represents the position of the Element within the current
    # session's dependency graph. A depth of zero represents the bottommost element.
    #
    def _set_depth(self, depth):
        self._depth = depth

    # _update_ready_for_runtime_and_cached()
    #
    # An Element becomes ready for runtime and cached once the following criteria
    # are met:
    #  1. The Element has a strong cache key
    #  2. The Element is cached (locally)
    #  3. The runtime dependencies of the Element are ready for runtime and cached.
    #
    # These criteria serve as potential trigger points as to when an Element may have
    # become ready for runtime and cached.
    #
    # Once an Element becomes ready for runtime and cached, we notify the reverse
    # runtime dependencies and the reverse build dependencies of the element, decrementing
    # the appropriate counters.
    #
    def _update_ready_for_runtime_and_cached(self):
        assert utils._is_in_main_thread(), "This has an impact on all elements and must be run in the main thread"

        if not self.__ready_for_runtime_and_cached:
            if self.__runtime_deps_uncached == 0 and self.__cache_key and self._cached_success():
                self.__ready_for_runtime_and_cached = True

                # Notify reverse dependencies
                for rdep in self.__reverse_runtime_deps:
                    rdep.__runtime_deps_uncached -= 1
                    assert not rdep.__runtime_deps_uncached < 0

                    # Try to notify reverse dependencies if all runtime deps are ready
                    if rdep.__runtime_deps_uncached == 0:
                        rdep._update_ready_for_runtime_and_cached()

                for rdep in self.__reverse_build_deps:
                    rdep.__build_deps_uncached -= 1
                    assert not rdep.__build_deps_uncached < 0

                    if rdep.__buildable_callback is not None and rdep._buildable():
                        rdep.__update_cache_key_non_strict()
                        rdep.__buildable_callback(rdep)
                        rdep.__buildable_callback = None

    # _walk_artifact_files()
    #
    # A generator which yields all of the files cached in the
    # element's artifact.
    #
    # Yields:
    #    (str): Filenames in the artifact
    #
    def _walk_artifact_files(self):
        yield from self.__artifact.get_files().walk()

    # _get_artifact()
    #
    # Return the Element's Artifact object
    #
    # Returns:
    #    (Artifact): The Artifact object of the Element
    #
    def _get_artifact(self):
        assert self.__artifact, "{}: has no Artifact object".format(self.name)
        return self.__artifact

    # _mimic_artifact()
    #
    # Assume the state dictated by the currently set artifact.
    #
    # This is used both when initializing an Element's state
    # from a loaded artifact, or after pulling the artifact from
    # a remote.
    #
    def _mimic_artifact(self):
        artifact = self._get_artifact()

        # Load bits which have been stored on the artifact
        #
        if artifact.cached():
            self.__environment = artifact.load_environment()
            self.__sandbox_config = artifact.load_sandbox_config()
            self.__variables = artifact.load_variables()
            self.__public = self.__artifact.load_public_data()

        self.__cache_key = artifact.strong_key
        self.__strict_cache_key = artifact.strict_key
        self.__weak_cache_key = artifact.weak_key

    # _add_build_dependency()
    #
    # Add a build dependency to the Element
    #
    # Args:
    #    (Element): The Element to add as a build dependency
    #
    def _add_build_dependency(self, dependency):
        self.__build_dependencies.append(dependency)

    # _file_is_whitelisted()
    #
    # Checks if a file is whitelisted in the overlap whitelist
    #
    # This is only internal (one underscore) and not locally private
    # because it needs to be proxied through ElementProxy.
    #
    # Args:
    #    path (str): The path to check
    #
    # Returns:
    #    (bool): True of the specified `path` is whitelisted
    #
    def _file_is_whitelisted(self, path):
        # Considered storing the whitelist regex for re-use, but public data
        # can be altered mid-build.
        # Public data is not guaranteed to stay the same for the duration of
        # the build, but I can think of no reason to change it mid-build.
        # If this ever changes, things will go wrong unexpectedly.
        if not self.__whitelist_regex:
            bstdata = self.get_public_data("bst")
            whitelist = bstdata.get_sequence("overlap-whitelist", default=[])
            whitelist_expressions = [utils._glob2re(self.__variables.subst(node)) for node in whitelist]
            expression = "^(?:" + "|".join(whitelist_expressions) + ")$"
            self.__whitelist_regex = re.compile(expression)
        return self.__whitelist_regex.match(os.path.join(os.sep, path))

    #############################################################
    #                   Private Local Methods                   #
    #############################################################

    # __get_proxy()
    #
    # Obtain a proxy for this element for the specified `owner`.
    #
    # We cache the proxies for plugin convenience, this allows plugins
    # compare proxies to other proxies returned to them, so they
    # can run valid statements such as `proxy_a is `proxy_b` or
    # `proxy_a in list_of_proxies`.
    #
    # Args:
    #    owner (Element): The owning element
    #
    # Returns:
    #    (ElementProxy): An ElementProxy to self, for owner.
    #
    def __get_proxy(self, owner: "Element") -> ElementProxy:
        with suppress(KeyError):
            return self.__proxies[owner]

        proxy = ElementProxy(owner, self)
        self.__proxies[owner] = proxy
        return proxy

    # __load_sources()
    #
    # Load the Source objects from the LoadElement
    #
    def __load_sources(self, load_element):
        project = self._get_project()
        workspace = self._get_workspace()
        meta_sources = []

        # If there's a workspace for this element then we just load a workspace
        # source plugin instead of the real plugins
        if workspace:
            workspace_node = {"kind": "workspace"}
            workspace_node["path"] = workspace.get_absolute_path()
            workspace_node["last_build"] = str(workspace.to_dict().get("last_build", ""))
            meta = MetaSource(
                self.name,
                0,
                self.get_kind(),
                "workspace",
                Node.from_dict(workspace_node),
                None,
                load_element.first_pass,
            )
            meta_sources.append(meta)
        else:
            sources = load_element.node.get_sequence(Symbol.SOURCES, default=[])
            for index, source in enumerate(sources):
                kind = source.get_scalar(Symbol.KIND)

                # The workspace source plugin is only valid for internal use
                if kind.as_str() == "workspace":
                    raise LoadError(
                        "{}: Invalid usage of workspace source kind".format(kind.get_provenance()),
                        LoadErrorReason.INVALID_DATA,
                    )
                del source[Symbol.KIND]

                # Directory is optional
                directory = source.get_str(Symbol.DIRECTORY, default=None)
                if directory:
                    del source[Symbol.DIRECTORY]
                meta_source = MetaSource(
                    self.name, index, self.get_kind(), kind.as_str(), source, directory, load_element.first_pass
                )
                meta_sources.append(meta_source)

        for meta_source in meta_sources:
            source = project.create_source(meta_source, variables=self.__variables)
            redundant_ref = source._load_ref()

            self.__sources.add_source(source)

            # Collect redundant refs which occurred at load time
            if redundant_ref is not None:
                self.__redundant_source_refs.append((source, redundant_ref))

    # __get_dependency_artifact_names()
    #
    # Retrieve the artifact names of all of the dependencies in _Scope.BUILD
    #
    # Returns:
    #    (list [str]): A list of refs of all dependencies in staging order.
    #
    def __get_dependency_artifact_names(self):
        return [
            os.path.join(dep.project_name, _get_normal_name(dep.name), dep._get_cache_key())
            for dep in self._dependencies(_Scope.BUILD)
        ]

    # __get_last_build_artifact()
    #
    # Return the Artifact of the previous build of this element,
    # if incremental build is available.
    #
    # Returns:
    #    (Artifact): The Artifact of the previous build or None
    #
    def __get_last_build_artifact(self):
        workspace = self._get_workspace()
        if not workspace:
            # Currently incremental builds are only supported for workspaces
            return None

        if not workspace.last_build:
            return None

        artifact = Artifact(self, self._get_context(), strong_key=workspace.last_build)

        if not artifact.cached():
            return None

        if not artifact.cached_buildtree():
            return None

        if not artifact.cached_sources():
            return None

        # Don't perform an incremental build if there has been a change in
        # build dependencies.
        old_dep_refs = artifact.get_dependency_artifact_names()
        new_dep_refs = self.__get_dependency_artifact_names()
        if old_dep_refs != new_dep_refs:
            return None

        return artifact

    # __configure_sandbox():
    #
    # Internal method for calling public abstract configure_sandbox() method.
    #
    def __configure_sandbox(self, sandbox):
        self.__batch_prepare_assemble = False

        self.configure_sandbox(sandbox)

    # __stage():
    #
    # Internal method for calling public abstract stage() method.
    #
    def __stage(self, sandbox):

        # Enable the overlap collector during the staging process
        with self.__collect_overlaps():
            self.stage(sandbox)

    # __prepare():
    #
    # Internal method for calling public abstract prepare() method.
    #
    def __prepare(self, sandbox):
        self.prepare(sandbox)

    # __preflight():
    #
    # A internal wrapper for calling the abstract preflight() method on
    # the element and its sources.
    #
    def __preflight(self):

        if self.BST_FORBID_RDEPENDS and self.BST_FORBID_BDEPENDS:
            if any(self._dependencies(_Scope.RUN, recurse=False)) or any(
                self._dependencies(_Scope.BUILD, recurse=False)
            ):
                raise ElementError(
                    "{}: Dependencies are forbidden for '{}' elements".format(self, self.get_kind()),
                    reason="element-forbidden-depends",
                )

        if self.BST_FORBID_RDEPENDS:
            if any(self._dependencies(_Scope.RUN, recurse=False)):
                raise ElementError(
                    "{}: Runtime dependencies are forbidden for '{}' elements".format(self, self.get_kind()),
                    reason="element-forbidden-rdepends",
                )

        if self.BST_FORBID_BDEPENDS:
            if any(self._dependencies(_Scope.BUILD, recurse=False)):
                raise ElementError(
                    "{}: Build dependencies are forbidden for '{}' elements".format(self, self.get_kind()),
                    reason="element-forbidden-bdepends",
                )

        if self.BST_FORBID_SOURCES:
            if any(self.sources()):
                raise ElementError(
                    "{}: Sources are forbidden for '{}' elements".format(self, self.get_kind()),
                    reason="element-forbidden-sources",
                )

        try:
            self.preflight()
        except BstError as e:
            # Prepend provenance to the error
            raise ElementError("{}: {}".format(self, e), reason=e.reason, detail=e.detail) from e

        self.__sources.preflight()

    # __get_base_key()
    #
    # Gets the base key for this element, the base key
    # is the part of the cache key which is element instance
    # specific and automatically generated by BuildStream core.
    #
    def __get_base_key(self):
        return {
            "build-root": self.get_variable("build-root"),
        }

    # __assert_cached()
    #
    # Raises an error if the artifact is not cached.
    #
    def __assert_cached(self):
        assert self._cached(), "{}: Missing artifact {}".format(self, self._get_display_key().brief)

    # __get_tainted():
    #
    # Checkes whether this artifact should be pushed to an artifact cache.
    #
    # Args:
    #    recalculate (bool) - Whether to force recalculation
    #
    # Returns:
    #    (bool) False if this artifact should be excluded from pushing.
    #
    # Note:
    #    This method should only be called after the element's
    #    artifact is present in the local artifact cache.
    #
    def __get_tainted(self, recalculate=False):
        if recalculate or self.__tainted is None:

            # Whether this artifact has a workspace
            workspaced = self.__artifact.get_metadata_workspaced()

            # Whether this artifact's dependencies have workspaces
            workspaced_dependencies = self.__artifact.get_metadata_workspaced_dependencies()

            # Other conditions should be or-ed
            self.__tainted = workspaced or workspaced_dependencies

        return self.__tainted

    # __collect_overlaps():
    #
    # A context manager for collecting overlap warnings and errors.
    #
    # Any places where code might call Element.stage_artifact()
    # or Element.stage_dependency_artifacts() should be run in
    # this context manager.
    #
    @contextmanager
    def __collect_overlaps(self):
        self._overlap_collector = OverlapCollector(self)
        yield
        self._overlap_collector = None

    # __sandbox():
    #
    # A context manager to prepare a Sandbox object at the specified directory,
    # if the directory is None, then a directory will be chosen automatically
    # in the configured build directory.
    #
    # Args:
    #    directory (str): The local directory where the sandbox will live, or None
    #    stdout (fileobject): The stream for stdout for the sandbox
    #    stderr (fileobject): The stream for stderr for the sandbox
    #    config (SandboxConfig): The SandboxConfig object
    #    allow_remote (bool): Whether the sandbox is allowed to be remote
    #
    # Yields:
    #    (Sandbox): A usable sandbox
    #
    @contextmanager
    def __sandbox(self, directory, stdout=None, stderr=None, config=None, allow_remote=True):
        context = self._get_context()
        project = self._get_project()
        platform = context.platform

        if self._get_workspace():
            output_node_properties = ["mtime"]
        else:
            output_node_properties = None

        if directory is not None and allow_remote and context.remote_execution_specs:

            self.info("Using a remote sandbox for artifact {} with directory '{}'".format(self.name, directory))

            output_files_required = context.require_artifact_files or self._artifact_files_required()

            sandbox = SandboxRemote(
                context,
                project,
                directory,
                plugin=self,
                stdout=stdout,
                stderr=stderr,
                config=config,
                output_files_required=output_files_required,
                output_node_properties=output_node_properties,
            )
            yield sandbox

        elif directory is not None and os.path.exists(directory):
            platform = context.platform
            platform.check_sandbox_config(config)

            sandbox = platform.create_sandbox(
                context,
                project,
                directory,
                plugin=self,
                stdout=stdout,
                stderr=stderr,
                config=config,
                output_node_properties=output_node_properties,
            )
            yield sandbox

        else:
            os.makedirs(context.builddir, exist_ok=True)

            # Recursive contextmanager...
            with utils._tempdir(
                prefix="{}-".format(self.normal_name), dir=context.builddir
            ) as rootdir, self.__sandbox(
                rootdir, stdout=stdout, stderr=stderr, config=config, allow_remote=allow_remote
            ) as sandbox:
                yield sandbox

    # __initialize_from_yaml()
    #
    # Normal element initialization procedure.
    #
    def __initialize_from_yaml(self, load_element: "LoadElement", plugin_conf: Dict[str, Any]):

        context = self._get_context()
        project = self._get_project()

        # Ensure we have loaded this class's defaults
        self.__init_defaults(project, plugin_conf, load_element.kind, load_element.first_pass)

        # Collect the composited variables and resolve them
        variables = self.__extract_variables(project, load_element)
        variables["element-name"] = self.name
        self.__variables = Variables(variables)
        if not load_element.first_pass:
            self.__variables.check()

        # Collect the composited environment now that we have variables
        unexpanded_env = self.__extract_environment(project, load_element)
        self.__variables.expand(unexpanded_env)
        self.__environment = unexpanded_env.strip_node_info()

        # Collect the environment nocache blacklist list
        nocache = self.__extract_env_nocache(project, load_element)
        self.__env_nocache = nocache

        # Grab public domain data declared for this instance
        self.__public = self.__extract_public(load_element)
        self.__variables.expand(self.__public)

        # Collect the composited element configuration and
        # ask the element to configure itself.
        self.__config = self.__extract_config(load_element)
        self.__variables.expand(self.__config)

        self._configure(self.__config)

        # Extract Sandbox config
        sandbox_config = self.__extract_sandbox_config(project, load_element)
        self.__variables.expand(sandbox_config)
        self.__sandbox_config = SandboxConfig.new_from_node(sandbox_config, platform=context.platform)

    # __initialize_from_artifact()
    #
    # Initialize the element state from an Artifact object
    #
    def __initialize_from_artifact(self, artifact: Artifact):
        self.__artifact = artifact
        self._mimic_artifact()

    @classmethod
    def __compose_default_splits(cls, project, defaults, first_pass):

        element_public = defaults.get_mapping(Symbol.PUBLIC, default={})
        element_bst = element_public.get_mapping("bst", default={})
        element_splits = element_bst.get_mapping("split-rules", default={})

        if first_pass:
            splits = element_splits.clone()
        else:
            assert project.splits is not None

            splits = project.splits.clone()
            # Extend project wide split rules with any split rules defined by the element
            element_splits._composite(splits)

        element_bst["split-rules"] = splits
        element_public["bst"] = element_bst
        defaults[Symbol.PUBLIC] = element_public

    @classmethod
    def __init_defaults(cls, project, plugin_conf, kind, first_pass):
        # Defaults are loaded once per class and then reused
        #
        if cls.__defaults is None:
            defaults = Node.from_dict({})

            if plugin_conf is not None:
                # Load the plugin's accompanying .yaml file if one was provided
                try:
                    defaults = _yaml.load(plugin_conf, os.path.basename(plugin_conf))
                except LoadError as e:
                    if e.reason != LoadErrorReason.MISSING_FILE:
                        raise e

            # Special case; compose any element-wide split-rules declarations
            cls.__compose_default_splits(project, defaults, first_pass)

            # Override the element's defaults with element specific
            # overrides from the project.conf
            if first_pass:
                elements = project.first_pass_config.element_overrides
            else:
                elements = project.element_overrides

            overrides = elements.get_mapping(kind, default=None)
            if overrides:
                overrides._composite(defaults)

            # Set the data class wide
            cls.__defaults = defaults

    # This will acquire the environment to be used when
    # creating sandboxes for this element
    #
    @classmethod
    def __extract_environment(cls, project, load_element):
        default_env = cls.__defaults.get_mapping(Symbol.ENVIRONMENT, default={})
        element_env = load_element.node.get_mapping(Symbol.ENVIRONMENT, default={}) or Node.from_dict({})

        if load_element.first_pass:
            environment = Node.from_dict({})
        else:
            environment = project.base_environment.clone()

        default_env._composite(environment)
        element_env._composite(environment)
        environment._assert_fully_composited()

        return environment

    @classmethod
    def __extract_env_nocache(cls, project, load_element):
        if load_element.first_pass:
            project_nocache = []
        else:
            project_nocache = project.base_env_nocache

        default_nocache = cls.__defaults.get_str_list(Symbol.ENV_NOCACHE, default=[])
        element_nocache = load_element.node.get_str_list(Symbol.ENV_NOCACHE, default=[])

        # Accumulate values from the element default, the project and the element
        # itself to form a complete list of nocache env vars.
        env_nocache = set(project_nocache + default_nocache + element_nocache)

        # Convert back to list now we know they're unique
        return list(env_nocache)

    # This will resolve the final variables to be used when
    # substituting command strings to be run in the sandbox
    #
    @classmethod
    def __extract_variables(cls, project, load_element):
        default_vars = cls.__defaults.get_mapping(Symbol.VARIABLES, default={})
        element_vars = load_element.node.get_mapping(Symbol.VARIABLES, default={}) or Node.from_dict({})

        if load_element.first_pass:
            variables = project.first_pass_config.base_variables.clone()
        else:
            variables = project.base_variables.clone()

        default_vars._composite(variables)
        element_vars._composite(variables)
        variables._assert_fully_composited()

        for var in ("project-name", "element-name", "max-jobs"):
            node = variables.get_node(var, allow_none=True)

            if node is None:
                continue

            provenance = node.get_provenance()
            if not provenance._is_synthetic:
                raise LoadError(
                    "{}: invalid redefinition of protected variable '{}'".format(provenance, var),
                    LoadErrorReason.PROTECTED_VARIABLE_REDEFINED,
                )

        return variables

    # This will resolve the final configuration to be handed
    # off to element.configure()
    #
    @classmethod
    def __extract_config(cls, load_element):
        element_config = load_element.node.get_mapping(Symbol.CONFIG, default={}) or Node.from_dict({})

        # The default config is already composited with the project overrides
        config = cls.__defaults.get_mapping(Symbol.CONFIG, default={})
        config = config.clone()

        element_config._composite(config)
        config._assert_fully_composited()

        return config

    # Sandbox-specific configuration data, to be passed to the sandbox's constructor.
    #
    @classmethod
    def __extract_sandbox_config(cls, project, load_element):
        element_sandbox = load_element.node.get_mapping(Symbol.SANDBOX, default={}) or Node.from_dict({})

        if load_element.first_pass:
            sandbox_config = Node.from_dict({})
        else:
            sandbox_config = project.sandbox.clone()

        # The default config is already composited with the project overrides
        sandbox_defaults = cls.__defaults.get_mapping(Symbol.SANDBOX, default={})
        sandbox_defaults = sandbox_defaults.clone()

        sandbox_defaults._composite(sandbox_config)
        element_sandbox._composite(sandbox_config)
        sandbox_config._assert_fully_composited()

        return sandbox_config

    # This makes a special exception for the split rules, which
    # elements may extend but whos defaults are defined in the project.
    #
    @classmethod
    def __extract_public(cls, load_element):
        element_public = load_element.node.get_mapping(Symbol.PUBLIC, default={}) or Node.from_dict({})

        base_public = cls.__defaults.get_mapping(Symbol.PUBLIC, default={})
        base_public = base_public.clone()

        base_bst = base_public.get_mapping("bst", default={})
        base_splits = base_bst.get_mapping("split-rules", default={})

        element_public = element_public.clone()
        element_bst = element_public.get_mapping("bst", default={})
        element_splits = element_bst.get_mapping("split-rules", default={})

        # Allow elements to extend the default splits defined in their project or
        # element specific defaults
        element_splits._composite(base_splits)

        element_bst["split-rules"] = base_splits
        element_public["bst"] = element_bst

        element_public._assert_fully_composited()

        return element_public

    def __init_splits(self):
        bstdata = self.get_public_data("bst")
        splits = bstdata.get_mapping("split-rules")
        self.__splits = {
            domain: re.compile("^(?:" + "|".join([utils._glob2re(r) for r in rules.as_str_list()]) + ")$")
            for domain, rules in splits.items()
        }

    # __split_filter():
    #
    # Returns True if the file with the specified `path` is included in the
    # specified split domains. This is used by `__split_filter_func()` to create
    # a filter callback.
    #
    # Args:
    #    element_domains (list): All domains for this element
    #    include (list): A list of domains to include files from
    #    exclude (list): A list of domains to exclude files from
    #    orphans (bool): Whether to include files not spoken for by split domains
    #    path (str): The relative path of the file
    #
    # Returns:
    #    (bool): Whether to include the specified file
    #
    def __split_filter(self, element_domains, include, exclude, orphans, path):
        # Absolute path is required for matching
        filename = os.path.join(os.sep, path)

        include_file = False
        exclude_file = False
        claimed_file = False

        for domain in element_domains:
            if self.__splits[domain].match(filename):
                claimed_file = True
                if domain in include:
                    include_file = True
                if domain in exclude:
                    exclude_file = True

        if orphans and not claimed_file:
            include_file = True

        return include_file and not exclude_file

    # __split_filter_func():
    #
    # Returns callable split filter function for use with `copy_files()`,
    # `link_files()` or `Directory.import_files()`.
    #
    # Args:
    #    include (list): An optional list of domains to include files from
    #    exclude (list): An optional list of domains to exclude files from
    #    orphans (bool): Whether to include files not spoken for by split domains
    #
    # Returns:
    #    (callable): Filter callback that returns True if the file is included
    #                in the specified split domains.
    #
    def __split_filter_func(self, include=None, exclude=None, orphans=True):
        # No splitting requested, no filter needed
        if orphans and not (include or exclude):
            return None

        if not self.__splits:
            self.__init_splits()

        element_domains = list(self.__splits.keys())
        if not include:
            include = element_domains
        if not exclude:
            exclude = []

        # Ignore domains that dont apply to this element
        #
        include = [domain for domain in include if domain in element_domains]
        exclude = [domain for domain in exclude if domain in element_domains]

        # The arguments element_domains, include, exclude, and orphans are
        # the same for all files. Use `partial` to create a function with
        # the required callback signature: a single `path` parameter.
        return partial(self.__split_filter, element_domains, include, exclude, orphans)

    def __compute_splits(self, include=None, exclude=None, orphans=True):
        filter_func = self.__split_filter_func(include=include, exclude=exclude, orphans=orphans)

        files_vdir = self.__artifact.get_files()

        element_files = files_vdir.list_relative_paths()

        if not filter_func:
            # No splitting requested, just report complete artifact
            yield from element_files
        else:
            for filename in element_files:
                if filter_func(filename):
                    yield filename

    def __load_build_result(self):
        self.__assert_cached()
        assert self.__build_result is None

        self.__build_result = self.__artifact.load_build_result()

    # __update_cache_keys()
    #
    # Updates weak and strict cache keys
    #
    # Note that it does not update *all* cache keys - In non-strict mode, the
    # strong cache key is updated in __update_cache_key_non_strict()
    #
    # If the element is not resolved, this is a no-op (since inconsistent
    # elements cannot have cache keys).
    #
    # The weak and strict cache keys will be calculated if not already
    # set.
    #
    # The weak cache key is a cache key that doesn't change when the
    # content of the build dependency graph changes (e.g., the configurations
    # or source versions of each dependency in Scope.BUILD), but does
    # take the shape of the build dependency graph into account, such
    # that adding or removing a dependency will still cause a rebuild to
    # occur (except for the strict dependency and BST_STRICT_REBUILD element
    # cases which are treated specially below).
    #
    # The strict cache key is a cache key that changes if any dependencies
    # in Scope.BUILD has changed in any way.
    #
    def __update_cache_keys(self):
        assert utils._is_in_main_thread(), "This has an impact on all elements and must be run in the main thread"

        if self.__strict_cache_key is not None:
            # Cache keys already calculated
            assert self.__weak_cache_key is not None
            return

        if not self._has_all_sources_resolved():
            # Tracking may still be pending
            return

        context = self._get_context()

        # Calculate the strict cache key
        dependencies = [[e.project_name, e.name, e.__strict_cache_key] for e in self._dependencies(_Scope.BUILD)]
        self.__strict_cache_key = self._calculate_cache_key(dependencies)

        if self.__strict_cache_key is None:
            # Cache keys cannot be calculated yet as a build dependency doesn't
            # have a cache key yet.
            return

        # Calculate weak cache key
        #
        # Weak cache key includes names of direct build dependencies
        # so as to only trigger rebuilds when the shape of the
        # dependencies change.
        #
        # Some conditions cause dependencies to be strict, such
        # that this element will be rebuilt anyway if the dependency
        # changes even in non strict mode, for these cases we just
        # encode the dependency's weak cache key instead of it's name.
        #
        dependencies = [
            [e.project_name, e.name, e._get_cache_key(strength=_KeyStrength.WEAK)]
            if self.BST_STRICT_REBUILD or e in self.__strict_dependencies
            else [e.project_name, e.name]
            for e in self._dependencies(_Scope.BUILD)
        ]

        self.__weak_cache_key = self._calculate_cache_key(dependencies)

        # As the strict cache key has already been calculated, it should always
        # be possible to calculate the weak cache key as well.
        assert self.__weak_cache_key is not None

        if context.get_strict():
            # In strict mode, the strong cache key always matches the strict cache key
            self.__cache_key = self.__strict_cache_key

        # If we've newly calculated a cache key, our artifact's
        # current state will also change - after all, we can now find
        # a potential existing artifact.
        self.__update_artifact_state()

        # Update the message kwargs in use for this plugin to dispatch messages with
        #
        self._message_kwargs["element_key"] = self._get_display_key()

    # __update_artifact_state()
    #
    # Updates the data involved in knowing about the artifact corresponding
    # to this element.
    #
    # If the state changes, this will subsequently call
    # `self.__schedule_assembly_when_necessary()` to schedule assembly if it becomes
    # possible.
    #
    # Element.__update_cache_keys() must be called before this to have
    # meaningful results, because the element must know its cache key before
    # it can check whether an artifact exists for that cache key.
    #
    def __update_artifact_state(self):
        assert utils._is_in_main_thread(), "This has an impact on all elements and must be run in the main thread"
        assert self.__artifact is None

        context = self._get_context()

        strict_artifact = Artifact(
            self,
            context,
            strong_key=self.__strict_cache_key,
            strict_key=self.__strict_cache_key,
            weak_key=self.__weak_cache_key,
        )
        if context.get_strict() or strict_artifact.cached():
            self.__artifact = strict_artifact
        else:
            self.__artifact = Artifact(
                self, context, strict_key=self.__strict_cache_key, weak_key=self.__weak_cache_key
            )

        if not context.get_strict() and self.__artifact.cached():
            # In non-strict mode, strong cache key becomes available when
            # the artifact is cached
            self.__update_cache_key_non_strict()

        self.__schedule_assembly_when_necessary()

        if self.__can_query_cache_callback is not None:
            self.__can_query_cache_callback(self)
            self.__can_query_cache_callback = None

    # __update_cache_key_non_strict()
    #
    # Calculates the strong cache key if it hasn't already been set.
    #
    # When buildstream runs in strict mode, this is identical to the
    # strict cache key, so no work needs to be done.
    #
    # When buildstream is not run in strict mode, this requires the artifact
    # state (as set in Element.__update_artifact_state()) to be set accordingly,
    # as the cache key can be loaded from the cache (possibly pulling from
    # a remote cache).
    #
    def __update_cache_key_non_strict(self):
        assert utils._is_in_main_thread(), "This has an impact on all elements and must be run in the main thread"

        # The final cache key can be None here only in non-strict mode
        if self.__cache_key is None:
            if self._pull_pending():
                # Effective strong cache key is unknown until after the pull
                pass
            elif self._cached():
                # Load the strong cache key from the artifact
                strong_key, _, _ = self.__artifact.get_metadata_keys()
                self.__cache_key = strong_key
            elif self.__assemble_scheduled or self.__assemble_done:
                # Artifact will or has been built, not downloaded
                dependencies = [[e.project_name, e.name, e._get_cache_key()] for e in self._dependencies(_Scope.BUILD)]
                self.__cache_key = self._calculate_cache_key(dependencies)

            if self.__cache_key is None:
                # Strong cache key could not be calculated yet
                return

            # The Element may have just become ready for runtime now that the
            # strong cache key has just been set
            self._update_ready_for_runtime_and_cached()

            # Now we have the strong cache key, update the Artifact
            self.__artifact._cache_key = self.__cache_key

            # Update the message kwargs in use for this plugin to dispatch messages with
            self._message_kwargs["element_key"] = self._get_display_key()


# _get_normal_name():
#
# Get the element name without path separators or
# the extension.
#
# Args:
#     element_name (str): The element's name
#
# Returns:
#     (str): The normalised element name
#
def _get_normal_name(element_name):
    return os.path.splitext(element_name.replace(os.sep, "-"))[0]


# _compose_artifact_name():
#
# Compose the completely resolved 'artifact_name' as a filepath
#
# Args:
#     project_name (str): The project's name
#     normal_name (str): The element's normalised name
#     cache_key (str): The relevant cache key
#
# Returns:
#     (str): The constructed artifact name path
#
def _compose_artifact_name(project_name, normal_name, cache_key):
    valid_chars = string.digits + string.ascii_letters + "-._"
    normal_name = "".join([x if x in valid_chars else "_" for x in normal_name])

    # Note that project names are not allowed to contain slashes. Element names containing
    # a '/' will have this replaced with a '-' upon Element object instantiation.
    return "{0}/{1}/{2}".format(project_name, normal_name, cache_key)
