summaryrefslogtreecommitdiff
path: root/src/buildstream/_elementproxy.py
diff options
context:
space:
mode:
authorTristan van Berkom <tristan@codethink.co.uk>2020-08-30 15:57:13 +0900
committerTristan van Berkom <tristan@codethink.co.uk>2020-09-04 18:22:38 +0900
commit1a3e4e89fc86b29342c9ec62ca8915b6eae084d2 (patch)
treed0e88bcc0fe25618306e93a3354026776bb9587b /src/buildstream/_elementproxy.py
parent97812cbb7d295cc3d270be9205cbc12313215028 (diff)
downloadbuildstream-1a3e4e89fc86b29342c9ec62ca8915b6eae084d2.tar.gz
element.py: Hide dependencies which are irrelevant to the Element
This is a large breaking change, a summary of the changes are that: * The Scope type is now private, since Element plugins do not have the choice to view any other scopes. * Element.dependencies() API change Now it accepts a "selection" (sequence) of dependency elements, so that Element.dependencies() can iterate over a collection of dependencies, ensuring that we iterate over every element only once even when we need to iterate over multiple element's dependencies. The old API is moved to Element._dependencies() and still used internally. * Element.stage_dependency_artifacts() API change This gets the same treatment as Element.dependencies(), and the old API is also preserved as Element._stage_dependency_artifacts(), so that the CLI can stage things for `bst artifact checkout` and such. * Element.search() API change The Scope argument is removed, and the old API is preserved as Element._search() temporarily, until we can remove this completely.
Diffstat (limited to 'src/buildstream/_elementproxy.py')
-rw-r--r--src/buildstream/_elementproxy.py56
1 files changed, 45 insertions, 11 deletions
diff --git a/src/buildstream/_elementproxy.py b/src/buildstream/_elementproxy.py
index 2022c2c81..acb08ce8b 100644
--- a/src/buildstream/_elementproxy.py
+++ b/src/buildstream/_elementproxy.py
@@ -16,9 +16,9 @@
#
# Authors:
# Tristan Van Berkom <tristan.vanberkom@codethink.co.uk>
-from typing import TYPE_CHECKING, cast, Optional, Iterator, Dict, List
+from typing import TYPE_CHECKING, cast, Optional, Iterator, Dict, List, Sequence
-from .types import Scope
+from .types import _Scope
from .utils import FileListResult
from ._pluginproxy import PluginProxy
@@ -55,15 +55,27 @@ class ElementProxy(PluginProxy):
def sources(self) -> Iterator["Source"]:
return cast("Element", self._plugin).sources()
- def dependencies(self, scope: Scope, *, recurse: bool = True, visited=None) -> Iterator["Element"]:
+ def dependencies(self, selection: Sequence["Element"] = None, *, recurse: bool = True) -> Iterator["Element"]:
#
- # FIXME: In the next phase, we will ensure that returned ElementProxy objects here are always
- # in the Scope.BUILD scope of the toplevel concrete Element class.
+ # When dependencies() is called on a dependency of the main plugin Element,
+ # we simply reroute the call to the original owning element, while specifying
+ # this element as the selection.
#
- return cast("Element", self._plugin).dependencies(scope, recurse=recurse, visited=visited)
+ # This ensures we only allow returning dependencies in the _Scope.RUN scope
+ # of this element.
+ #
+ if selection is None:
+ selection = [cast("Element", self._plugin)]
+
+ # Return the iterable from the called generator, this is more performant than yielding from it
+ return cast("Element", self._owner).dependencies(selection, recurse=recurse)
- def search(self, scope: Scope, name: str) -> Optional["Element"]:
- return cast("Element", self._plugin).search(scope, name)
+ def search(self, name: str) -> Optional["Element"]:
+ #
+ # Similarly to dependencies() above, we only search in the _Scope.RUN
+ # of dependencies of the active element plugin.
+ #
+ return cast("Element", self._plugin)._search(_Scope.RUN, name)
def node_subst_vars(self, node: "ScalarNode") -> str:
return cast("Element", self._plugin).node_subst_vars(node)
@@ -95,15 +107,20 @@ class ElementProxy(PluginProxy):
def stage_dependency_artifacts(
self,
sandbox: "Sandbox",
- scope: Scope,
+ selection: Sequence["Element"] = None,
*,
path: str = None,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True
) -> None:
- return cast("Element", self._plugin).stage_dependency_artifacts(
- sandbox, scope, path=path, include=include, exclude=exclude, orphans=orphans
+ #
+ # Same approach used here as in Element.dependencies()
+ #
+ if selection is None:
+ selection = [cast("Element", self._plugin)]
+ cast("Element", self._owner).stage_dependency_artifacts(
+ sandbox, selection, path=path, include=include, exclude=exclude, orphans=orphans
)
def integrate(self, sandbox: "Sandbox") -> None:
@@ -120,3 +137,20 @@ class ElementProxy(PluginProxy):
def get_logs(self) -> List[str]:
return cast("Element", self._plugin).get_logs()
+
+ ##############################################################
+ # Element Internal APIs #
+ ##############################################################
+ #
+ # Some functions the Element expects to call directly on the
+ # proxy.
+ #
+ def _dependencies(self, scope, *, recurse=True, visited=None):
+ #
+ # We use a return statement even though this is a generator, simply
+ # to avoid the generator overhead of yielding each element.
+ #
+ return cast("Element", self._plugin)._dependencies(scope, recurse=recurse, visited=visited)
+
+ def _file_is_whitelisted(self, path):
+ return cast("Element", self._plugin)._file_is_whitelisted(path)