def _load_artifact()

in src/buildstream/element.py [0:0]


    def _load_artifact(self, *, pull, strict=None):
        context = self._get_context()

        if strict is None:
            strict = context.get_strict()

        pull_buildtrees = context.pull_buildtrees and not self._get_workspace()

        # First check whether we already have the strict artifact in the local cache
        artifact = Artifact(
            self,
            context,
            strict_key=self.__strict_cache_key,
            strong_key=self.__strict_cache_key,
            weak_key=self.__weak_cache_key,
        )
        artifact.query_cache()

        self.__pull_pending = False
        if not pull and not artifact.cached(buildtree=pull_buildtrees):
            if self.__artifacts.has_fetch_remotes(plugin=self) and not self._get_workspace():
                # Artifact is not completely available in cache and artifact remote server is available.
                # Stop artifact loading here as pull is required to proceed.
                self.__pull_pending = True

        # Attempt to pull artifact with the strict cache key
        pulled = pull and artifact.pull(pull_buildtrees=pull_buildtrees)

        # Ignore failed build artifacts if a retry was requested
        ignore_failed_artifact = context.build and context.build_retry_failed

        if artifact.cached() or strict:
            if artifact.cached() and ignore_failed_artifact:
                success, _, _ = artifact.load_build_result()
                if not success:

                    self.info(
                        "Discarded failed build",
                        detail="Discarded '{}'\n".format(artifact.strong_key)
                        + "because retrying failed builds is enabled.",
                    )

                    artifact = Artifact(
                        self,
                        context,
                        strong_key=self.__cache_key,
                        strict_key=self.__strict_cache_key,
                        weak_key=self.__weak_cache_key,
                    )
                    artifact._cached = False
                    pulled = False

            self.__artifact = artifact
            return pulled
        elif self.__pull_pending:
            return False

        # In non-strict mode retry with weak cache key
        artifact = Artifact(self, context, strict_key=self.__strict_cache_key, weak_key=self.__weak_cache_key)
        artifact.query_cache()

        # Attempt to pull artifact with the weak cache key
        pulled = pull and artifact.pull(pull_buildtrees=pull_buildtrees)

        # Automatically retry building failed builds in non-strict mode, because
        # dependencies may have changed since the last build which might cause this
        # failed build to succeed.
        #
        # When not building (e.g. `bst show`, `bst artifact push` etc), we do not drop
        # the failed artifact, the retry only occurs at build time.
        #
        if context.build and artifact.cached():
            success, _, _ = artifact.load_build_result()
            if not success:
                #
                # If we could resolve the stong cache key for this element at this time,
                # we could compare the artifact key against the resolved strong key.
                #
                # If we could assert that artifact state is never consulted in advance
                # of resolving the strong key, then we could discard the loaded artifact
                # at that time instead.
                #
                # Since neither of these are true, we settle for always retrying a failed
                # build in non-strict mode unless the failed artifact's strong key is
                # equal to the resolved strict key.
                #
                if ignore_failed_artifact or artifact.strong_key != self.__strict_cache_key:

                    if ignore_failed_artifact:
                        reason = "because retrying failed builds is enabled."
                    else:
                        reason = "in non strict mode because intermediate dependencies may have changed."
                    self.info(
                        "Discarded failed build",
                        detail="Discarded '{}'\n{}".format(artifact.strong_key, reason),
                    )

                    artifact = Artifact(
                        self,
                        context,
                        strict_key=self.__strict_cache_key,
                        weak_key=self.__weak_cache_key,
                    )
                    artifact._cached = False
                    pulled = False

        self.__artifact = artifact
        return pulled