summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbst-marge-bot <marge-bot@buildstream.build>2020-04-29 09:06:05 +0000
committerbst-marge-bot <marge-bot@buildstream.build>2020-04-29 09:06:05 +0000
commite70d77f997b7e94b4f7b8901fdec0973e2e9328c (patch)
tree5ebf22492da221cf0c606a56036cec39eb8ce450
parent82eb1d4271bb634f248bc9e1770119d2815d7cd6 (diff)
parent1339b0e56c5a685d5da0f617a0b6f205c03d1251 (diff)
downloadbuildstream-e70d77f997b7e94b4f7b8901fdec0973e2e9328c.tar.gz
Merge branch 'tristan/plugin-versions-refactor' into 'master'
Plugin loading refactor, implement BST_MIN_VERSION See merge request BuildStream/buildstream!1885
-rw-r--r--doc/examples/flatpak-autotools/project.conf2
-rw-r--r--setup.cfg2
-rw-r--r--src/buildstream/_exceptions.py4
-rw-r--r--src/buildstream/_pluginfactory/__init__.py20
-rw-r--r--src/buildstream/_pluginfactory/elementfactory.py (renamed from src/buildstream/_elementfactory.py)21
-rw-r--r--src/buildstream/_pluginfactory/pluginfactory.py (renamed from src/buildstream/_plugincontext.py)158
-rw-r--r--src/buildstream/_pluginfactory/pluginorigin.py130
-rw-r--r--src/buildstream/_pluginfactory/sourcefactory.py (renamed from src/buildstream/_sourcefactory.py)21
-rw-r--r--src/buildstream/_project.py101
-rw-r--r--src/buildstream/plugin.py31
-rw-r--r--src/buildstream/plugins/elements/autotools.py4
-rw-r--r--src/buildstream/plugins/elements/compose.py2
-rw-r--r--src/buildstream/plugins/elements/filter.py2
-rw-r--r--src/buildstream/plugins/elements/import.py2
-rw-r--r--src/buildstream/plugins/elements/junction.py2
-rw-r--r--src/buildstream/plugins/elements/manual.py4
-rw-r--r--src/buildstream/plugins/elements/pip.py4
-rw-r--r--src/buildstream/plugins/elements/script.py4
-rw-r--r--src/buildstream/plugins/elements/stack.py3
-rw-r--r--src/buildstream/plugins/sources/bzr.py2
-rw-r--r--src/buildstream/plugins/sources/git.py3
-rw-r--r--src/buildstream/plugins/sources/local.py2
-rw-r--r--src/buildstream/plugins/sources/patch.py2
-rw-r--r--src/buildstream/plugins/sources/pip.py2
-rw-r--r--src/buildstream/plugins/sources/remote.py2
-rw-r--r--src/buildstream/plugins/sources/tar.py2
-rw-r--r--src/buildstream/plugins/sources/workspace.py3
-rw-r--r--src/buildstream/plugins/sources/zip.py2
-rw-r--r--src/buildstream/testing/_sourcetests/utils.py2
-rw-r--r--tests/elements/filter/basic/element_plugins/dynamic.py3
-rw-r--r--tests/elements/filter/basic/project.conf2
-rw-r--r--tests/format/project.py4
-rw-r--r--tests/format/project/duplicate-plugins/project.conf8
-rw-r--r--tests/format/project/local-plugin/project.conf2
-rw-r--r--tests/format/project/plugin-allowed/plugins/foo.py3
-rw-r--r--tests/format/project/plugin-allowed/project.conf2
-rw-r--r--tests/format/project/plugin-forbidden/forbidden-plugins/forbidden-plugin.py3
-rw-r--r--tests/format/project/plugin-no-load-ref/plugins/noloadref.py3
-rw-r--r--tests/format/project/plugin-preflight-error/errorplugin/preflighterror.py3
-rw-r--r--tests/format/project/plugin-preflight-error/project.conf2
-rw-r--r--tests/frontend/configurable_warnings.py4
-rw-r--r--tests/frontend/configuredwarning/plugins/corewarn.py3
-rw-r--r--tests/frontend/configuredwarning/plugins/warninga.py3
-rw-r--r--tests/frontend/configuredwarning/plugins/warningb.py3
-rw-r--r--tests/frontend/configuredwarning/project.conf4
-rw-r--r--tests/frontend/consistencyerror/plugins/consistencybug.py3
-rw-r--r--tests/frontend/consistencyerror/plugins/consistencyerror.py3
-rw-r--r--tests/frontend/consistencyerror/project.conf4
-rw-r--r--tests/frontend/mirror.py2
-rw-r--r--tests/frontend/project/plugins/randomelement.py3
-rw-r--r--tests/frontend/project/sources/fetch_source.py3
-rw-r--r--tests/frontend/push.py2
-rw-r--r--tests/internals/pluginfactory.py287
-rw-r--r--tests/internals/pluginfactory/anotherelement/__init__.py0
-rw-r--r--tests/internals/pluginfactory/anotherelement/foo.py9
-rw-r--r--tests/internals/pluginfactory/anothersource/__init__.py0
-rw-r--r--tests/internals/pluginfactory/anothersource/foo.py9
-rw-r--r--tests/internals/pluginfactory/badsetup/__init__.py0
-rw-r--r--tests/internals/pluginfactory/badsetup/foo.py6
-rw-r--r--tests/internals/pluginfactory/badversionelement/__init__.py0
-rw-r--r--tests/internals/pluginfactory/badversionelement/foo.py11
-rw-r--r--tests/internals/pluginfactory/badversionsource/__init__.py0
-rw-r--r--tests/internals/pluginfactory/badversionsource/foo.py11
-rw-r--r--tests/internals/pluginfactory/customelement/__init__.py0
-rw-r--r--tests/internals/pluginfactory/customelement/foo.py9
-rw-r--r--tests/internals/pluginfactory/customsource/__init__.py0
-rw-r--r--tests/internals/pluginfactory/customsource/foo.py9
-rw-r--r--tests/internals/pluginfactory/nosetup/__init__.py0
-rw-r--r--tests/internals/pluginfactory/notatype/__init__.py0
-rw-r--r--tests/internals/pluginfactory/notatype/foo.py6
-rw-r--r--tests/internals/pluginfactory/wrongtype/__init__.py0
-rw-r--r--tests/internals/pluginfactory/wrongtype/foo.py12
-rw-r--r--tests/internals/pluginloading.py22
-rw-r--r--tests/internals/pluginloading/badversionelement/customelements/__init__.py0
-rw-r--r--tests/internals/pluginloading/badversionelement/customelements/foo.py19
-rw-r--r--tests/internals/pluginloading/badversionelement/elements/simple.bst4
-rw-r--r--tests/internals/pluginloading/badversionelement/project.conf10
-rw-r--r--tests/internals/pluginloading/badversionsource/customsources/__init__.py0
-rw-r--r--tests/internals/pluginloading/badversionsource/customsources/foo.py16
-rw-r--r--tests/internals/pluginloading/badversionsource/elements/simple.bst6
-rw-r--r--tests/internals/pluginloading/badversionsource/project.conf10
-rw-r--r--tests/internals/pluginloading/customelement/pluginelements/foo.py3
-rw-r--r--tests/internals/pluginloading/customelement/project.conf2
-rw-r--r--tests/internals/pluginloading/customsource/pluginsources/foo.py3
-rw-r--r--tests/internals/pluginloading/customsource/project.conf2
-rw-r--r--tests/plugins/deprecationwarnings.py (renamed from tests/plugins/deprecationwarnings/deprecationwarnings.py)2
-rw-r--r--tests/plugins/deprecationwarnings/__init__.py0
-rw-r--r--tests/plugins/deprecationwarnings/elements/deprecated.bst (renamed from tests/plugins/deprecationwarnings/project/elements/deprecated.bst)0
-rw-r--r--tests/plugins/deprecationwarnings/plugins/elements/deprecated_plugin.py (renamed from tests/plugins/deprecationwarnings/project/plugins/elements/deprecated_plugin.py)1
-rw-r--r--tests/plugins/deprecationwarnings/plugins/elements/deprecated_plugin.yaml (renamed from tests/plugins/deprecationwarnings/project/plugins/elements/deprecated_plugin.yaml)0
-rw-r--r--tests/plugins/deprecationwarnings/project.conf (renamed from tests/plugins/deprecationwarnings/project/project.conf)2
-rw-r--r--tests/plugins/loading.py202
-rw-r--r--tests/plugins/loading/plugins/elements/incompatiblemajor/incompatiblemajor.py10
-rw-r--r--tests/plugins/loading/plugins/elements/incompatibleminor/incompatibleminor.py10
-rw-r--r--tests/plugins/loading/plugins/elements/malformedminversion/malformedminversion.py11
-rw-r--r--tests/plugins/loading/plugins/elements/nominversion/nominversion.py10
-rw-r--r--tests/plugins/loading/plugins/nosetup/nosetup.py (renamed from tests/internals/pluginfactory/nosetup/foo.py)0
-rw-r--r--tests/plugins/loading/plugins/setupnotfunction/setupnotfunction.py6
-rw-r--r--tests/plugins/loading/plugins/setupreturnsbadtype/setupreturnsbadtype.py15
-rw-r--r--tests/plugins/loading/plugins/setupreturnsnottype/setupreturnsnottype.py8
-rw-r--r--tests/plugins/loading/plugins/sources/incompatiblemajor/incompatiblemajor.py10
-rw-r--r--tests/plugins/loading/plugins/sources/incompatibleminor/incompatibleminor.py10
-rw-r--r--tests/plugins/loading/plugins/sources/malformedminversion/malformedminversion.py11
-rw-r--r--tests/plugins/loading/plugins/sources/nominversion/nominversion.py10
-rw-r--r--tests/plugins/loading/project.conf8
-rw-r--r--tests/sourcecache/project/plugins/elements/always_fail.py3
-rw-r--r--tests/sourcecache/project/project.conf2
-rw-r--r--tests/sources/no-fetch-cached/plugins/sources/always_cached.py2
-rw-r--r--tests/sources/no-fetch-cached/project.conf2
-rw-r--r--tests/sources/previous_source_access/plugins/sources/foo_transform.py1
-rw-r--r--tests/sources/previous_source_access/project.conf2
-rw-r--r--tests/sources/project_key_test/plugins/sources/key-test.py2
-rw-r--r--tests/sources/project_key_test/project.conf2
-rw-r--r--tox.ini2
114 files changed, 729 insertions, 692 deletions
diff --git a/doc/examples/flatpak-autotools/project.conf b/doc/examples/flatpak-autotools/project.conf
index 08dc6ee32..d7a0a396d 100644
--- a/doc/examples/flatpak-autotools/project.conf
+++ b/doc/examples/flatpak-autotools/project.conf
@@ -19,4 +19,4 @@ plugins:
- origin: pip
package-name: bst-plugins-experimental
sources:
- ostree: 0
+ - ostree
diff --git a/setup.cfg b/setup.cfg
index 7d3599e14..0853264f6 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -9,7 +9,7 @@ parentdir_prefix = BuildStream-
[tool:pytest]
addopts = --verbose --basetemp ./tmp --durations=20 --timeout=1800
-norecursedirs = src tests/integration/project integration-cache tmp __pycache__ .eggs
+norecursedirs = src tests/integration/project tests/plugins/loading integration-cache tmp __pycache__ .eggs
python_files = tests/*/*.py
env =
D:BST_TEST_SUITE=True
diff --git a/src/buildstream/_exceptions.py b/src/buildstream/_exceptions.py
index f92ab822b..30fc26e71 100644
--- a/src/buildstream/_exceptions.py
+++ b/src/buildstream/_exceptions.py
@@ -124,8 +124,8 @@ class BstError(Exception):
# or by the base :class:`.Plugin` element itself.
#
class PluginError(BstError):
- def __init__(self, message, reason=None, temporary=False):
- super().__init__(message, domain=ErrorDomain.PLUGIN, reason=reason, temporary=temporary)
+ def __init__(self, message, *, reason=None, detail=None, temporary=False):
+ super().__init__(message, domain=ErrorDomain.PLUGIN, detail=detail, reason=reason, temporary=temporary)
# LoadError
diff --git a/src/buildstream/_pluginfactory/__init__.py b/src/buildstream/_pluginfactory/__init__.py
new file mode 100644
index 000000000..fe69b6e77
--- /dev/null
+++ b/src/buildstream/_pluginfactory/__init__.py
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2020 Codethink Limited
+#
+# 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/>.
+#
+
+from .pluginorigin import PluginOrigin, PluginOriginType
+from .sourcefactory import SourceFactory
+from .elementfactory import ElementFactory
diff --git a/src/buildstream/_elementfactory.py b/src/buildstream/_pluginfactory/elementfactory.py
index 89e01a885..8879a4173 100644
--- a/src/buildstream/_elementfactory.py
+++ b/src/buildstream/_pluginfactory/elementfactory.py
@@ -17,9 +17,10 @@
# Authors:
# Tristan Van Berkom <tristan.vanberkom@codethink.co.uk>
-from . import _site
-from ._plugincontext import PluginContext
-from .element import Element
+from .. import _site
+from ..element import Element
+
+from .pluginfactory import PluginFactory
# A ElementFactory creates Element instances
@@ -27,18 +28,12 @@ from .element import Element
#
# Args:
# plugin_base (PluginBase): The main PluginBase object to work with
-# plugin_origins (list): Data used to search for external Element plugins
#
-class ElementFactory(PluginContext):
- def __init__(self, plugin_base, *, format_versions={}, plugin_origins=None):
+class ElementFactory(PluginFactory):
+ def __init__(self, plugin_base):
super().__init__(
- plugin_base,
- Element,
- [_site.element_plugins],
- "buildstream.plugins.elements",
- plugin_origins=plugin_origins,
- format_versions=format_versions,
+ plugin_base, Element, [_site.element_plugins], "buildstream.plugins.elements",
)
# create():
@@ -60,6 +55,4 @@ class ElementFactory(PluginContext):
def create(self, context, project, meta):
element_type, default_config = self.lookup(meta.kind)
element = element_type(context, project, meta, default_config)
- version = self._format_versions.get(meta.kind, 0)
- self._assert_plugin_format(element, version)
return element
diff --git a/src/buildstream/_plugincontext.py b/src/buildstream/_pluginfactory/pluginfactory.py
index 3a195e239..27321c62f 100644
--- a/src/buildstream/_plugincontext.py
+++ b/src/buildstream/_pluginfactory/pluginfactory.py
@@ -20,9 +20,11 @@
import os
import inspect
-from ._exceptions import PluginError, LoadError
-from .exceptions import LoadErrorReason
-from . import utils
+from .. import utils
+from ..utils import UtilError
+from .._exceptions import PluginError
+
+from .pluginorigin import PluginOrigin, PluginOriginType
# A Context for loading plugin types
@@ -32,9 +34,6 @@ from . import utils
# base_type (type): A base object type for this context
# site_plugin_path (str): Path to where buildstream keeps plugins
# entrypoint_group (str): Name of the entry point group that provides plugins
-# plugin_origins (list): Data used to search for plugins
-# format_versions (dict): A dict of meta.kind to the integer minimum
-# version number for each plugin to be loaded
#
# Since multiple pipelines can be processed recursively
# within the same interpretor, it's important that we have
@@ -43,16 +42,8 @@ from . import utils
# a given BuildStream project are isolated to their respective
# Pipelines.
#
-class PluginContext:
- def __init__(
- self, plugin_base, base_type, site_plugin_path, entrypoint_group, *, plugin_origins=None, format_versions={}
- ):
-
- # For pickling across processes, make sure this context has a unique
- # identifier, which we prepend to the identifier of each PluginSource.
- # This keeps plugins loaded during the first and second pass distinct
- # from eachother.
- self._identifier = str(id(self))
+class PluginFactory:
+ def __init__(self, plugin_base, base_type, site_plugin_path, entrypoint_group):
# The plugin kinds which were loaded
self.loaded_dependencies = []
@@ -60,16 +51,22 @@ class PluginContext:
#
# Private members
#
+
+ # For pickling across processes, make sure this context has a unique
+ # identifier, which we prepend to the identifier of each PluginSource.
+ # This keeps plugins loaded during the first and second pass distinct
+ # from eachother.
+ self._identifier = str(id(self))
+
self._base_type = base_type # The base class plugins derive from
self._types = {} # Plugin type lookup table by kind
- self._plugin_origins = plugin_origins or []
+ self._origins = {} # PluginOrigin lookup table by kind
# The PluginSource object
self._plugin_base = plugin_base
self._site_plugin_path = site_plugin_path
self._entrypoint_group = entrypoint_group
self._alternate_sources = {}
- self._format_versions = format_versions
self._init_site_source()
@@ -127,6 +124,23 @@ class PluginContext:
def lookup(self, kind):
return self._ensure_plugin(kind)
+ # register_plugin_origin():
+ #
+ # Registers the PluginOrigin to use for the given plugin kind
+ #
+ # Args:
+ # kind (str): The kind identifier of the Plugin
+ # origin (PluginOrigin): The PluginOrigin providing the plugin
+ #
+ def register_plugin_origin(self, kind: str, origin: PluginOrigin):
+ if kind in self._origins:
+ raise PluginError(
+ "More than one {} plugin registered as kind '{}'".format(self._base_type.__name__, kind),
+ reason="duplicate-plugin",
+ )
+
+ self._origins[kind] = origin
+
# all_loaded_plugins():
#
# Returns: an iterable over all the loaded plugins.
@@ -186,39 +200,27 @@ class PluginContext:
def _ensure_plugin(self, kind):
if kind not in self._types:
- # Check whether the plugin is specified in plugins
source = None
defaults = None
- loaded_dependency = False
-
- for origin in self._plugin_origins:
- if kind not in origin.get_str_list("plugins"):
- continue
-
- if origin.get_str("origin") == "local":
- local_path = origin.get_str("path")
- source = self._get_local_plugin_source(local_path)
- elif origin.get_str("origin") == "pip":
- package_name = origin.get_str("package-name")
- source, defaults = self._get_pip_plugin_source(package_name, kind)
+
+ origin = self._origins.get(kind, None)
+ if origin:
+ # Try getting the plugin source from a registered origin
+ if origin.origin_type == PluginOriginType.LOCAL:
+ source = self._get_local_plugin_source(origin.path)
+ elif origin.origin_type == PluginOriginType.PIP:
+ source, defaults = self._get_pip_plugin_source(origin.package_name, kind)
else:
- raise PluginError(
- "Failed to load plugin '{}': "
- "Unexpected plugin origin '{}'".format(kind, origin.get_str("origin"))
- )
- loaded_dependency = True
- break
-
- # Fall back to getting the source from site
- if not source:
+ assert False, "Encountered invalid plugin origin type"
+ else:
+ # Try getting it from the core plugins
if kind not in self._site_source.list_plugins():
raise PluginError("No {} type registered for kind '{}'".format(self._base_type.__name__, kind))
source = self._site_source
self._types[kind] = self._load_plugin(source, kind, defaults)
- if loaded_dependency:
- self.loaded_dependencies.append(kind)
+ self.loaded_dependencies.append(kind)
return self._types[kind]
@@ -240,15 +242,18 @@ class PluginContext:
plugin_type = plugin.setup()
except AttributeError as e:
raise PluginError(
- "{} plugin '{}' did not provide a setup() function".format(self._base_type.__name__, kind)
+ "{} plugin '{}' did not provide a setup() function".format(self._base_type.__name__, kind),
+ reason="missing-setup-function",
) from e
except TypeError as e:
raise PluginError(
- "setup symbol in {} plugin '{}' is not a function".format(self._base_type.__name__, kind)
+ "setup symbol in {} plugin '{}' is not a function".format(self._base_type.__name__, kind),
+ reason="setup-is-not-function",
) from e
self._assert_plugin(kind, plugin_type)
- self._assert_version(kind, plugin_type)
+ self._assert_min_version(kind, plugin_type)
+
return (plugin_type, defaults)
def _assert_plugin(self, kind, plugin_type):
@@ -262,45 +267,54 @@ class PluginContext:
raise PluginError(
"{} plugin '{}' returned type '{}', which is not a subclass of {}".format(
self._base_type.__name__, kind, plugin_type.__name__, self._base_type.__name__
- )
+ ),
+ reason="setup-returns-bad-type",
)
except TypeError as e:
raise PluginError(
"{} plugin '{}' returned something that is not a type (expected subclass of {})".format(
self._base_type.__name__, kind, self._base_type.__name__
- )
+ ),
+ reason="setup-returns-not-type",
) from e
- def _assert_version(self, kind, plugin_type):
+ def _assert_min_version(self, kind, plugin_type):
- # Now assert BuildStream version
- bst_major, bst_minor = utils.get_bst_version()
+ if plugin_type.BST_MIN_VERSION is None:
+ raise PluginError(
+ "{} plugin '{}' did not specify BST_MIN_VERSION".format(self._base_type.__name__, kind),
+ reason="missing-min-version",
+ detail="Are you trying to use a BuildStream 1 plugin with a BuildStream 2 project ?",
+ )
- req_major = plugin_type.BST_REQUIRED_VERSION_MAJOR
- req_minor = plugin_type.BST_REQUIRED_VERSION_MINOR
+ try:
+ min_version_major, min_version_minor = utils._parse_version(plugin_type.BST_MIN_VERSION)
+ except UtilError as e:
+ raise PluginError(
+ "{} plugin '{}' specified malformed BST_MIN_VERSION: {}".format(
+ self._base_type.__name__, kind, plugin_type.BST_MIN_VERSION
+ ),
+ reason="malformed-min-version",
+ detail="BST_MIN_VERSION must be specified as 'MAJOR.MINOR' with "
+ + "numeric major and minor minimum required version numbers",
+ ) from e
- if (bst_major, bst_minor) < (req_major, req_minor):
+ bst_major, bst_minor = utils._get_bst_api_version()
+
+ if min_version_major != bst_major:
raise PluginError(
- "BuildStream {}.{} is too old for {} plugin '{}' (requires {}.{})".format(
- bst_major,
- bst_minor,
- self._base_type.__name__,
- kind,
- plugin_type.BST_REQUIRED_VERSION_MAJOR,
- plugin_type.BST_REQUIRED_VERSION_MINOR,
- )
+ "{} plugin '{}' requires BuildStream {}, but is being loaded with BuildStream {}".format(
+ self._base_type.__name__, kind, min_version_major, bst_major
+ ),
+ reason="incompatible-major-version",
+ detail="You will need to find the correct version of this plugin for your project.",
)
- # _assert_plugin_format()
- #
- # Helper to raise a PluginError if the loaded plugin is of a lesser version then
- # the required version for this plugin
- #
- def _assert_plugin_format(self, plugin, version):
- if plugin.BST_FORMAT_VERSION < version:
- raise LoadError(
- "{}: Format version {} is too old for requested version {}".format(
- plugin, plugin.BST_FORMAT_VERSION, version
+ if min_version_minor > bst_minor:
+ raise PluginError(
+ "{} plugin '{}' requires BuildStream {}, but is being loaded with BuildStream {}.{}".format(
+ self._base_type.__name__, kind, plugin_type.BST_MIN_VERSION, bst_major, bst_minor
),
- LoadErrorReason.UNSUPPORTED_PLUGIN,
+ reason="incompatible-minor-version",
+ detail="Please upgrade to BuildStream {}".format(plugin_type.BST_MIN_VERSION),
)
diff --git a/src/buildstream/_pluginfactory/pluginorigin.py b/src/buildstream/_pluginfactory/pluginorigin.py
new file mode 100644
index 000000000..50852711b
--- /dev/null
+++ b/src/buildstream/_pluginfactory/pluginorigin.py
@@ -0,0 +1,130 @@
+#
+# Copyright (C) 2020 Codethink Limited
+#
+# 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/>.
+#
+
+import os
+
+from ..types import FastEnum
+
+
+# PluginOriginType:
+#
+# An enumeration depicting the type of plugin origin
+#
+class PluginOriginType(FastEnum):
+ LOCAL = "local"
+ PIP = "pip"
+
+
+# PluginOrigin
+#
+# Base class holding common properties of all origins.
+#
+class PluginOrigin:
+
+ # Common fields valid for all plugin origins
+ _COMMON_CONFIG_KEYS = ["origin", "sources", "elements"]
+
+ def __init__(self, origin_type):
+
+ # Public
+ self.origin_type = origin_type
+ self.elements = []
+ self.sources = []
+
+ # Private
+ self._project = None
+ self._kinds = {}
+
+ # new_from_node()
+ #
+ # Load a PluginOrigin from the YAML in project.conf
+ #
+ # Args:
+ # project (Project): The project from whence this origin is loaded
+ # origin_node (MappingNode): The node defining this origin
+ #
+ # Returns:
+ # (PluginOrigin): The newly created PluginOrigin
+ #
+ @classmethod
+ def new_from_node(cls, project, origin_node):
+
+ origin_type = origin_node.get_enum("origin", PluginOriginType)
+
+ if origin_type == PluginOriginType.LOCAL:
+ origin = PluginOriginLocal()
+ elif origin_type == PluginOriginType.PIP:
+ origin = PluginOriginPip()
+
+ origin._project = project
+ origin._load(origin_node)
+
+ origin.elements = origin_node.get_str_list("elements", [])
+ origin.sources = origin_node.get_str_list("sources", [])
+
+ return origin
+
+ # _load()
+ #
+ # Abstract method for loading data from the origin node, this
+ # method should not load the source and element lists.
+ #
+ # Args:
+ # origin_node (MappingNode): The node defining this origin
+ #
+ def _load(self, origin_node):
+ pass
+
+
+# PluginOriginLocal
+#
+# PluginOrigin for local plugins
+#
+class PluginOriginLocal(PluginOrigin):
+ def __init__(self):
+ super().__init__(PluginOriginType.LOCAL)
+
+ # An absolute path to where the plugin can be found
+ #
+ self.path = None
+
+ def _load(self, origin_node):
+
+ origin_node.validate_keys(["path", *PluginOrigin._COMMON_CONFIG_KEYS])
+
+ path_node = origin_node.get_scalar("path")
+ path = self._project.get_path_from_node(path_node, check_is_dir=True)
+
+ self.path = os.path.join(self._project.directory, path)
+
+
+# PluginOriginPip
+#
+# PluginOrigin for pip plugins
+#
+class PluginOriginPip(PluginOrigin):
+ def __init__(self):
+ super().__init__(PluginOriginType.PIP)
+
+ # The pip package name to extract plugins from
+ #
+ self.package_name = None
+
+ def _load(self, origin_node):
+
+ origin_node.validate_keys(["package-name", *PluginOrigin._COMMON_CONFIG_KEYS])
+ self.package_name = origin_node.get_str("package-name")
diff --git a/src/buildstream/_sourcefactory.py b/src/buildstream/_pluginfactory/sourcefactory.py
index 254c482d6..9f6a09784 100644
--- a/src/buildstream/_sourcefactory.py
+++ b/src/buildstream/_pluginfactory/sourcefactory.py
@@ -17,9 +17,10 @@
# Authors:
# Tristan Van Berkom <tristan.vanberkom@codethink.co.uk>
-from . import _site
-from ._plugincontext import PluginContext
-from .source import Source
+from .. import _site
+from ..source import Source
+
+from .pluginfactory import PluginFactory
# A SourceFactory creates Source instances
@@ -27,18 +28,12 @@ from .source import Source
#
# Args:
# plugin_base (PluginBase): The main PluginBase object to work with
-# plugin_origins (list): Data used to search for external Source plugins
#
-class SourceFactory(PluginContext):
- def __init__(self, plugin_base, *, format_versions={}, plugin_origins=None):
+class SourceFactory(PluginFactory):
+ def __init__(self, plugin_base):
super().__init__(
- plugin_base,
- Source,
- [_site.source_plugins],
- "buildstream.plugins.sources",
- format_versions=format_versions,
- plugin_origins=plugin_origins,
+ plugin_base, Source, [_site.source_plugins], "buildstream.plugins.sources",
)
# create():
@@ -61,6 +56,4 @@ class SourceFactory(PluginContext):
def create(self, context, project, meta):
source_type, _ = self.lookup(meta.kind)
source = source_type(context, project, meta)
- version = self._format_versions.get(meta.kind, 0)
- self._assert_plugin_format(source, version)
return source
diff --git a/src/buildstream/_project.py b/src/buildstream/_project.py
index 3527d211f..40524d7ad 100644
--- a/src/buildstream/_project.py
+++ b/src/buildstream/_project.py
@@ -36,13 +36,11 @@ from ._artifactcache import ArtifactCache
from ._sourcecache import SourceCache
from .node import ScalarNode, SequenceNode, _assert_symbol_name
from .sandbox import SandboxRemote
-from ._elementfactory import ElementFactory
-from ._sourcefactory import SourceFactory
+from ._pluginfactory import ElementFactory, SourceFactory, PluginOrigin
from .types import CoreWarnings
from ._projectrefs import ProjectRefs, ProjectRefStorage
from ._loader import Loader
from .element import Element
-from .types import FastEnum
from ._message import Message, MessageType
from ._includes import Includes
from ._workspaces import WORKSPACE_PROJECT_FILE
@@ -52,13 +50,6 @@ from ._workspaces import WORKSPACE_PROJECT_FILE
_PROJECT_CONF_FILE = "project.conf"
-# List of all places plugins can come from
-class PluginOrigins(FastEnum):
- CORE = "core"
- LOCAL = "local"
- PIP = "pip"
-
-
# HostMount()
#
# A simple object describing the behavior of
@@ -951,87 +942,19 @@ class Project:
return project_directory, workspace_element
def _load_plugin_factories(self, config, output):
- plugin_source_origins = [] # Origins of custom sources
- plugin_element_origins = [] # Origins of custom elements
-
- # Plugin origins and versions
- origins = config.get_sequence("plugins", default=[])
- source_format_versions = {}
- element_format_versions = {}
- for origin in origins:
- allowed_origin_fields = [
- "origin",
- "sources",
- "elements",
- "package-name",
- "path",
- ]
- origin.validate_keys(allowed_origin_fields)
-
- # Store source versions for checking later
- source_versions = origin.get_mapping("sources", default={})
- for key in source_versions.keys():
- if key in source_format_versions:
- raise LoadError("Duplicate listing of source '{}'".format(key), LoadErrorReason.INVALID_YAML)
- source_format_versions[key] = source_versions.get_int(key)
-
- # Store element versions for checking later
- element_versions = origin.get_mapping("elements", default={})
- for key in element_versions.keys():
- if key in element_format_versions:
- raise LoadError("Duplicate listing of element '{}'".format(key), LoadErrorReason.INVALID_YAML)
- element_format_versions[key] = element_versions.get_int(key)
-
- # Store the origins if they're not 'core'.
- # core elements are loaded by default, so storing is unnecessary.
- origin_value = origin.get_enum("origin", PluginOrigins)
-
- if origin_value != PluginOrigins.CORE:
- self._store_origin(origin, "sources", plugin_source_origins)
- self._store_origin(origin, "elements", plugin_element_origins)
-
+ # Create the factories
pluginbase = PluginBase(package="buildstream.plugins")
- output.element_factory = ElementFactory(
- pluginbase, plugin_origins=plugin_element_origins, format_versions=element_format_versions
- )
- output.source_factory = SourceFactory(
- pluginbase, plugin_origins=plugin_source_origins, format_versions=source_format_versions
- )
+ output.element_factory = ElementFactory(pluginbase)
+ output.source_factory = SourceFactory(pluginbase)
- # _store_origin()
- #
- # Helper function to store plugin origins
- #
- # Args:
- # origin (node) - a node indicating the origin of a group of
- # plugins.
- # plugin_group (str) - The name of the type of plugin that is being
- # loaded
- # destination (list) - A list of nodes to store the origins in
- #
- # Raises:
- # LoadError if 'origin' is an unexpected value
- def _store_origin(self, origin, plugin_group, destination):
- expected_groups = ["sources", "elements"]
- if plugin_group not in expected_groups:
- raise LoadError(
- "Unexpected plugin group: {}, expecting {}".format(plugin_group, expected_groups),
- LoadErrorReason.INVALID_DATA,
- )
- if plugin_group in origin.keys():
- origin_node = origin.clone()
- plugins = origin.get_mapping(plugin_group, default={})
- origin_node["plugins"] = plugins.keys()
-
- for group in expected_groups:
- if group in origin_node:
- del origin_node[group]
-
- if origin_node.get_enum("origin", PluginOrigins) == PluginOrigins.LOCAL:
- path = self.get_path_from_node(origin.get_scalar("path"), check_is_dir=True)
- # paths are passed in relative to the project, but must be absolute
- origin_node["path"] = os.path.join(self.directory, path)
- destination.append(origin_node)
+ # Load the plugin origins and register them to their factories
+ origins = config.get_sequence("plugins", default=[])
+ for origin_node in origins:
+ origin = PluginOrigin.new_from_node(self, origin_node)
+ for kind in origin.elements:
+ output.element_factory.register_plugin_origin(kind, origin)
+ for kind in origin.sources:
+ output.source_factory.register_plugin_origin(kind, origin)
# _warning_is_fatal():
#
diff --git a/src/buildstream/plugin.py b/src/buildstream/plugin.py
index 2182f5a08..935db6523 100644
--- a/src/buildstream/plugin.py
+++ b/src/buildstream/plugin.py
@@ -148,25 +148,30 @@ class Plugin:
which are included in the buildstream namespace.
"""
- BST_REQUIRED_VERSION_MAJOR = 0
- """Minimum required major version"""
+ BST_MIN_VERSION = None
+ """The minimum required version of BuildStream required by this plugin.
- BST_REQUIRED_VERSION_MINOR = 0
- """Minimum required minor version"""
+ The version must be expressed as the string *"<major>.<minor>"*, where the
+ *major* version number is the API version and the *minor* version number is
+ the revision of the same BuildStream API where new symbols might have been
+ added to the API.
- BST_FORMAT_VERSION = 0
- """The plugin's YAML format version
+ **Example:**
- This should be set to ``1`` the first time any new configuration
- is understood by your :func:`Plugin.configure() <buildstream.plugin.Plugin.configure>`
- implementation and subsequently bumped every time your
- configuration is enhanced.
+ The following statement means that this plugin works with *BuildStream 2.X*,
+ only if *X >= 2*:
+
+ .. code:: python
+
+ class Foo(Source):
+
+ # Our plugin requires 2.2
+ BST_MIN_VERSION = "2.2"
.. note::
- Plugins are expected to maintain backward compatibility
- in the format and configurations they expose. The versioning
- is intended to track availability of new features only.
+ This version works exactly the same was as the :ref:`min-version <project_min_version>`
+ which must be specified in the project.conf file.
"""
BST_PLUGIN_DEPRECATED = False
diff --git a/src/buildstream/plugins/elements/autotools.py b/src/buildstream/plugins/elements/autotools.py
index c4396c5cc..5f5a1b465 100644
--- a/src/buildstream/plugins/elements/autotools.py
+++ b/src/buildstream/plugins/elements/autotools.py
@@ -60,6 +60,10 @@ from buildstream import BuildElement, SandboxFlags
# Element implementation for the 'autotools' kind.
class AutotoolsElement(BuildElement):
+ # pylint: disable=attribute-defined-outside-init
+
+ BST_MIN_VERSION = "2.0"
+
# Enable command batching across prepare() and assemble()
def configure_sandbox(self, sandbox):
super().configure_sandbox(sandbox)
diff --git a/src/buildstream/plugins/elements/compose.py b/src/buildstream/plugins/elements/compose.py
index 6e4aed193..9c136df9d 100644
--- a/src/buildstream/plugins/elements/compose.py
+++ b/src/buildstream/plugins/elements/compose.py
@@ -41,6 +41,8 @@ from buildstream import Element, Scope
class ComposeElement(Element):
# pylint: disable=attribute-defined-outside-init
+ BST_MIN_VERSION = "2.0"
+
# The compose element's output is its dependencies, so
# we must rebuild if the dependencies change even when
# not in strict build plans.
diff --git a/src/buildstream/plugins/elements/filter.py b/src/buildstream/plugins/elements/filter.py
index 37b205fe2..62c04e027 100644
--- a/src/buildstream/plugins/elements/filter.py
+++ b/src/buildstream/plugins/elements/filter.py
@@ -140,6 +140,8 @@ from buildstream import Element, ElementError, Scope
class FilterElement(Element):
# pylint: disable=attribute-defined-outside-init
+ BST_MIN_VERSION = "2.0"
+
BST_ARTIFACT_VERSION = 1
# The filter element's output is its dependencies, so
diff --git a/src/buildstream/plugins/elements/import.py b/src/buildstream/plugins/elements/import.py
index 2bbd11354..d9961aa6f 100644
--- a/src/buildstream/plugins/elements/import.py
+++ b/src/buildstream/plugins/elements/import.py
@@ -38,6 +38,8 @@ from buildstream import Element, ElementError
class ImportElement(Element):
# pylint: disable=attribute-defined-outside-init
+ BST_MIN_VERSION = "2.0"
+
# Import elements do not run any commands
BST_RUN_COMMANDS = False
diff --git a/src/buildstream/plugins/elements/junction.py b/src/buildstream/plugins/elements/junction.py
index 46c4ddf68..917482d63 100644
--- a/src/buildstream/plugins/elements/junction.py
+++ b/src/buildstream/plugins/elements/junction.py
@@ -165,6 +165,8 @@ from buildstream._pipeline import PipelineError
class JunctionElement(Element):
# pylint: disable=attribute-defined-outside-init
+ BST_MIN_VERSION = "2.0"
+
# Junctions are not allowed any dependencies
BST_FORBID_BDEPENDS = True
BST_FORBID_RDEPENDS = True
diff --git a/src/buildstream/plugins/elements/manual.py b/src/buildstream/plugins/elements/manual.py
index c95b8e5a2..125c5142b 100644
--- a/src/buildstream/plugins/elements/manual.py
+++ b/src/buildstream/plugins/elements/manual.py
@@ -36,6 +36,10 @@ from buildstream import BuildElement, SandboxFlags
# Element implementation for the 'manual' kind.
class ManualElement(BuildElement):
+ # pylint: disable=attribute-defined-outside-init
+
+ BST_MIN_VERSION = "2.0"
+
# Enable command batching across prepare() and assemble()
def configure_sandbox(self, sandbox):
super().configure_sandbox(sandbox)
diff --git a/src/buildstream/plugins/elements/pip.py b/src/buildstream/plugins/elements/pip.py
index 06e187b69..5f805f460 100644
--- a/src/buildstream/plugins/elements/pip.py
+++ b/src/buildstream/plugins/elements/pip.py
@@ -36,6 +36,10 @@ from buildstream import BuildElement, SandboxFlags
# Element implementation for the 'pip' kind.
class PipElement(BuildElement):
+ # pylint: disable=attribute-defined-outside-init
+
+ BST_MIN_VERSION = "2.0"
+
# Enable command batching across prepare() and assemble()
def configure_sandbox(self, sandbox):
super().configure_sandbox(sandbox)
diff --git a/src/buildstream/plugins/elements/script.py b/src/buildstream/plugins/elements/script.py
index e355e5f05..9d780ebe2 100644
--- a/src/buildstream/plugins/elements/script.py
+++ b/src/buildstream/plugins/elements/script.py
@@ -40,6 +40,10 @@ import buildstream
# Element implementation for the 'script' kind.
class ScriptElement(buildstream.ScriptElement):
+ # pylint: disable=attribute-defined-outside-init
+
+ BST_MIN_VERSION = "2.0"
+
def configure(self, node):
for n in node.get_sequence("layout", []):
dst = self.node_subst_vars(n.get_scalar("destination"))
diff --git a/src/buildstream/plugins/elements/stack.py b/src/buildstream/plugins/elements/stack.py
index df11a257f..b15f67073 100644
--- a/src/buildstream/plugins/elements/stack.py
+++ b/src/buildstream/plugins/elements/stack.py
@@ -29,6 +29,9 @@ from buildstream import Element
# Element implementation for the 'stack' kind.
class StackElement(Element):
+ # pylint: disable=attribute-defined-outside-init
+
+ BST_MIN_VERSION = "2.0"
# This plugin does not produce any artifacts when built
BST_ELEMENT_HAS_ARTIFACT = False
diff --git a/src/buildstream/plugins/sources/bzr.py b/src/buildstream/plugins/sources/bzr.py
index 8a02eff95..93b554472 100644
--- a/src/buildstream/plugins/sources/bzr.py
+++ b/src/buildstream/plugins/sources/bzr.py
@@ -66,6 +66,8 @@ from buildstream import utils
class BzrSource(Source):
# pylint: disable=attribute-defined-outside-init
+ BST_MIN_VERSION = "2.0"
+
def configure(self, node):
node.validate_keys(["url", "track", "ref", *Source.COMMON_CONFIG_KEYS])
diff --git a/src/buildstream/plugins/sources/git.py b/src/buildstream/plugins/sources/git.py
index 473166132..6427d4b04 100644
--- a/src/buildstream/plugins/sources/git.py
+++ b/src/buildstream/plugins/sources/git.py
@@ -156,7 +156,8 @@ from buildstream import _GitSourceBase
class GitSource(_GitSourceBase):
- pass
+
+ BST_MIN_VERSION = "2.0"
# Plugin entry point
diff --git a/src/buildstream/plugins/sources/local.py b/src/buildstream/plugins/sources/local.py
index 57bcf14df..c39e09417 100644
--- a/src/buildstream/plugins/sources/local.py
+++ b/src/buildstream/plugins/sources/local.py
@@ -44,6 +44,8 @@ from buildstream import Source, SourceError
class LocalSource(Source):
# pylint: disable=attribute-defined-outside-init
+ BST_MIN_VERSION = "2.0"
+
BST_STAGE_VIRTUAL_DIRECTORY = True
BST_KEY_REQUIRES_STAGE = True
diff --git a/src/buildstream/plugins/sources/patch.py b/src/buildstream/plugins/sources/patch.py
index f33dfedec..18672df8a 100644
--- a/src/buildstream/plugins/sources/patch.py
+++ b/src/buildstream/plugins/sources/patch.py
@@ -52,6 +52,8 @@ from buildstream import utils
class PatchSource(Source):
# pylint: disable=attribute-defined-outside-init
+ BST_MIN_VERSION = "2.0"
+
BST_REQUIRES_PREVIOUS_SOURCES_STAGE = True
def configure(self, node):
diff --git a/src/buildstream/plugins/sources/pip.py b/src/buildstream/plugins/sources/pip.py
index 69c08e81f..c0885ce5a 100644
--- a/src/buildstream/plugins/sources/pip.py
+++ b/src/buildstream/plugins/sources/pip.py
@@ -98,6 +98,8 @@ _SDIST_RE = re.compile(r"^([\w.-]+?)-((?:[\d.]+){2,})\.(?:tar|tar.bz2|tar.gz|tar
class PipSource(Source):
# pylint: disable=attribute-defined-outside-init
+ BST_MIN_VERSION = "2.0"
+
# We need access to previous sources at track time to use requirements.txt
# but not at fetch time as self.ref should contain sufficient information
# for this plugin
diff --git a/src/buildstream/plugins/sources/remote.py b/src/buildstream/plugins/sources/remote.py
index 29333c0d9..57d8743a7 100644
--- a/src/buildstream/plugins/sources/remote.py
+++ b/src/buildstream/plugins/sources/remote.py
@@ -55,6 +55,8 @@ from ._downloadablefilesource import DownloadableFileSource
class RemoteSource(DownloadableFileSource):
# pylint: disable=attribute-defined-outside-init
+ BST_MIN_VERSION = "2.0"
+
def configure(self, node):
super().configure(node)
diff --git a/src/buildstream/plugins/sources/tar.py b/src/buildstream/plugins/sources/tar.py
index fc4f5736a..793fd11c9 100644
--- a/src/buildstream/plugins/sources/tar.py
+++ b/src/buildstream/plugins/sources/tar.py
@@ -92,6 +92,8 @@ class ReadableTarInfo(tarfile.TarInfo):
class TarSource(DownloadableFileSource):
# pylint: disable=attribute-defined-outside-init
+ BST_MIN_VERSION = "2.0"
+
def configure(self, node):
super().configure(node)
diff --git a/src/buildstream/plugins/sources/workspace.py b/src/buildstream/plugins/sources/workspace.py
index 13e2bb37d..796f2b3d9 100644
--- a/src/buildstream/plugins/sources/workspace.py
+++ b/src/buildstream/plugins/sources/workspace.py
@@ -45,6 +45,9 @@ from buildstream.node import MappingNode
class WorkspaceSource(Source):
# pylint: disable=attribute-defined-outside-init
+
+ BST_MIN_VERSION = "2.0"
+
BST_STAGE_VIRTUAL_DIRECTORY = True
BST_KEY_REQUIRES_STAGE = True
diff --git a/src/buildstream/plugins/sources/zip.py b/src/buildstream/plugins/sources/zip.py
index 47823dfde..c112cf10e 100644
--- a/src/buildstream/plugins/sources/zip.py
+++ b/src/buildstream/plugins/sources/zip.py
@@ -69,6 +69,8 @@ from ._downloadablefilesource import DownloadableFileSource
class ZipSource(DownloadableFileSource):
# pylint: disable=attribute-defined-outside-init
+ BST_MIN_VERSION = "2.0"
+
def configure(self, node):
super().configure(node)
diff --git a/src/buildstream/testing/_sourcetests/utils.py b/src/buildstream/testing/_sourcetests/utils.py
index 116506807..4cfb696bd 100644
--- a/src/buildstream/testing/_sourcetests/utils.py
+++ b/src/buildstream/testing/_sourcetests/utils.py
@@ -71,7 +71,7 @@ def add_plugins_conf(project, plugin_kind):
if plugin_package is not None:
project_conf["plugins"] = [
- {"origin": "pip", "package-name": plugin_package, "sources": {plugin_kind: 0,},},
+ {"origin": "pip", "package-name": plugin_package, "sources": [plugin_kind],},
]
_yaml.roundtrip_dump(project_conf, project_conf_file)
diff --git a/tests/elements/filter/basic/element_plugins/dynamic.py b/tests/elements/filter/basic/element_plugins/dynamic.py
index bf079111f..db92a6647 100644
--- a/tests/elements/filter/basic/element_plugins/dynamic.py
+++ b/tests/elements/filter/basic/element_plugins/dynamic.py
@@ -3,6 +3,9 @@ from buildstream import Element, Scope
# Copies files from the dependent element but inserts split-rules using dynamic data
class DynamicElement(Element):
+
+ BST_MIN_VERSION = "2.0"
+
def configure(self, node):
node.validate_keys(["split-rules"])
self.split_rules = {key: value.as_str_list() for key, value in node.get_mapping("split-rules").items()}
diff --git a/tests/elements/filter/basic/project.conf b/tests/elements/filter/basic/project.conf
index e0b487d01..023943f79 100644
--- a/tests/elements/filter/basic/project.conf
+++ b/tests/elements/filter/basic/project.conf
@@ -5,4 +5,4 @@ plugins:
- origin: local
path: element_plugins
elements:
- dynamic: 0
+ - dynamic
diff --git a/tests/format/project.py b/tests/format/project.py
index c2e2f733f..c4b2a480a 100644
--- a/tests/format/project.py
+++ b/tests/format/project.py
@@ -177,7 +177,7 @@ def test_plugin_no_load_ref(cli, datafiles, ref_storage):
"name": "test",
"min-version": "2.0",
"ref-storage": ref_storage,
- "plugins": [{"origin": "local", "path": "plugins", "sources": {"noloadref": 0}}],
+ "plugins": [{"origin": "local", "path": "plugins", "sources": ["noloadref"]}],
}
_yaml.roundtrip_dump(config, os.path.join(project, "project.conf"))
@@ -202,7 +202,7 @@ def test_plugin_preflight_error(cli, datafiles):
def test_duplicate_plugins(cli, datafiles):
project = os.path.join(datafiles.dirname, datafiles.basename, "duplicate-plugins")
result = cli.run(project=project, silent=True, args=["show", "element.bst"])
- result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.INVALID_YAML)
+ result.assert_main_error(ErrorDomain.PLUGIN, "duplicate-plugin")
# Assert that we get a different cache key for target.bst, depending
diff --git a/tests/format/project/duplicate-plugins/project.conf b/tests/format/project/duplicate-plugins/project.conf
index a413e6137..495ba0678 100644
--- a/tests/format/project/duplicate-plugins/project.conf
+++ b/tests/format/project/duplicate-plugins/project.conf
@@ -5,12 +5,12 @@ plugins:
- origin: local
path: bar
elements:
- foo: 0
+ - foo
sources:
- frob: 0
+ - frob
- origin: local
path: baz
elements:
- foo: 0
+ - foo
sources:
- frob: 0
+ - frob
diff --git a/tests/format/project/local-plugin/project.conf b/tests/format/project/local-plugin/project.conf
index ccb6ef433..7d8cc1aea 100644
--- a/tests/format/project/local-plugin/project.conf
+++ b/tests/format/project/local-plugin/project.conf
@@ -4,4 +4,4 @@ plugins:
- origin: local
path: plugins
sources:
- mysource: 0
+ - mysource
diff --git a/tests/format/project/plugin-allowed/plugins/foo.py b/tests/format/project/plugin-allowed/plugins/foo.py
index bf884233c..76d9bfd3c 100644
--- a/tests/format/project/plugin-allowed/plugins/foo.py
+++ b/tests/format/project/plugin-allowed/plugins/foo.py
@@ -2,6 +2,9 @@ from buildstream import Element
class FooElement(Element):
+
+ BST_MIN_VERSION = "2.0"
+
def configure(self, config):
pass
diff --git a/tests/format/project/plugin-allowed/project.conf b/tests/format/project/plugin-allowed/project.conf
index 3896b7bc2..97107edf6 100644
--- a/tests/format/project/plugin-allowed/project.conf
+++ b/tests/format/project/plugin-allowed/project.conf
@@ -5,4 +5,4 @@ plugins:
- origin: local
path: plugins
elements:
- foo: 0
+ - foo
diff --git a/tests/format/project/plugin-forbidden/forbidden-plugins/forbidden-plugin.py b/tests/format/project/plugin-forbidden/forbidden-plugins/forbidden-plugin.py
index bf884233c..76d9bfd3c 100644
--- a/tests/format/project/plugin-forbidden/forbidden-plugins/forbidden-plugin.py
+++ b/tests/format/project/plugin-forbidden/forbidden-plugins/forbidden-plugin.py
@@ -2,6 +2,9 @@ from buildstream import Element
class FooElement(Element):
+
+ BST_MIN_VERSION = "2.0"
+
def configure(self, config):
pass
diff --git a/tests/format/project/plugin-no-load-ref/plugins/noloadref.py b/tests/format/project/plugin-no-load-ref/plugins/noloadref.py
index e2fe0ac46..2b8fd0b51 100644
--- a/tests/format/project/plugin-no-load-ref/plugins/noloadref.py
+++ b/tests/format/project/plugin-no-load-ref/plugins/noloadref.py
@@ -6,6 +6,9 @@ from buildstream import Source
# Use this to test that the core behaves as expected with such plugins.
#
class NoLoadRefSource(Source):
+
+ BST_MIN_VERSION = "2.0"
+
def configure(self, node):
pass
diff --git a/tests/format/project/plugin-preflight-error/errorplugin/preflighterror.py b/tests/format/project/plugin-preflight-error/errorplugin/preflighterror.py
index db2895f8b..a03cb64ee 100644
--- a/tests/format/project/plugin-preflight-error/errorplugin/preflighterror.py
+++ b/tests/format/project/plugin-preflight-error/errorplugin/preflighterror.py
@@ -2,6 +2,9 @@ from buildstream import Source, SourceError
class PreflightErrorSource(Source):
+
+ BST_MIN_VERSION = "2.0"
+
def configure(self, node):
pass
diff --git a/tests/format/project/plugin-preflight-error/project.conf b/tests/format/project/plugin-preflight-error/project.conf
index 07d60daf2..ed1ddb99f 100644
--- a/tests/format/project/plugin-preflight-error/project.conf
+++ b/tests/format/project/plugin-preflight-error/project.conf
@@ -9,4 +9,4 @@ plugins:
- origin: local
path: errorplugin
sources:
- preflighterror: 0
+ - preflighterror
diff --git a/tests/frontend/configurable_warnings.py b/tests/frontend/configurable_warnings.py
index e61db6c37..53409a512 100644
--- a/tests/frontend/configurable_warnings.py
+++ b/tests/frontend/configurable_warnings.py
@@ -18,9 +18,7 @@ def get_project(fatal_warnings):
"name": "test",
"min-version": "2.0",
"element-path": "elements",
- "plugins": [
- {"origin": "local", "path": "plugins", "elements": {"warninga": 0, "warningb": 0, "corewarn": 0,}}
- ],
+ "plugins": [{"origin": "local", "path": "plugins", "elements": ["warninga", "warningb", "corewarn"]}],
"fatal-warnings": fatal_warnings,
}
diff --git a/tests/frontend/configuredwarning/plugins/corewarn.py b/tests/frontend/configuredwarning/plugins/corewarn.py
index bef0a4904..bcd40753c 100644
--- a/tests/frontend/configuredwarning/plugins/corewarn.py
+++ b/tests/frontend/configuredwarning/plugins/corewarn.py
@@ -3,6 +3,9 @@ from buildstream.plugin import CoreWarnings
class CoreWarn(Element):
+
+ BST_MIN_VERSION = "2.0"
+
def configure(self, node):
pass
diff --git a/tests/frontend/configuredwarning/plugins/warninga.py b/tests/frontend/configuredwarning/plugins/warninga.py
index 9fd8dc61b..4ad0f3d20 100644
--- a/tests/frontend/configuredwarning/plugins/warninga.py
+++ b/tests/frontend/configuredwarning/plugins/warninga.py
@@ -4,6 +4,9 @@ WARNING_A = "warning-a"
class WarningA(Element):
+
+ BST_MIN_VERSION = "2.0"
+
def configure(self, node):
pass
diff --git a/tests/frontend/configuredwarning/plugins/warningb.py b/tests/frontend/configuredwarning/plugins/warningb.py
index 64d25ef39..c7a995cf8 100644
--- a/tests/frontend/configuredwarning/plugins/warningb.py
+++ b/tests/frontend/configuredwarning/plugins/warningb.py
@@ -4,6 +4,9 @@ WARNING_B = "warning-b"
class WarningB(Element):
+
+ BST_MIN_VERSION = "2.0"
+
def configure(self, node):
pass
diff --git a/tests/frontend/configuredwarning/project.conf b/tests/frontend/configuredwarning/project.conf
index 195ee176a..9d75ad18b 100644
--- a/tests/frontend/configuredwarning/project.conf
+++ b/tests/frontend/configuredwarning/project.conf
@@ -5,5 +5,5 @@ plugins:
- origin: local
path: element_plugins
elements:
- warninga: 0
- warningb: 0
+ - warninga
+ - warningb
diff --git a/tests/frontend/consistencyerror/plugins/consistencybug.py b/tests/frontend/consistencyerror/plugins/consistencybug.py
index abcbbc997..1952894ca 100644
--- a/tests/frontend/consistencyerror/plugins/consistencybug.py
+++ b/tests/frontend/consistencyerror/plugins/consistencybug.py
@@ -2,6 +2,9 @@ from buildstream import Source
class ConsistencyBugSource(Source):
+
+ BST_MIN_VERSION = "2.0"
+
def configure(self, node):
pass
diff --git a/tests/frontend/consistencyerror/plugins/consistencyerror.py b/tests/frontend/consistencyerror/plugins/consistencyerror.py
index 2e30d4842..34af45782 100644
--- a/tests/frontend/consistencyerror/plugins/consistencyerror.py
+++ b/tests/frontend/consistencyerror/plugins/consistencyerror.py
@@ -2,6 +2,9 @@ from buildstream import Source, SourceError
class ConsistencyErrorSource(Source):
+
+ BST_MIN_VERSION = "2.0"
+
def configure(self, node):
pass
diff --git a/tests/frontend/consistencyerror/project.conf b/tests/frontend/consistencyerror/project.conf
index d28ba12df..f5c1b39c5 100644
--- a/tests/frontend/consistencyerror/project.conf
+++ b/tests/frontend/consistencyerror/project.conf
@@ -9,5 +9,5 @@ plugins:
- origin: local
path: plugins
sources:
- consistencyerror: 0
- consistencybug: 0
+ - consistencyerror
+ - consistencybug
diff --git a/tests/frontend/mirror.py b/tests/frontend/mirror.py
index 848047ee8..bffc754e7 100644
--- a/tests/frontend/mirror.py
+++ b/tests/frontend/mirror.py
@@ -49,7 +49,7 @@ def generate_project():
{"name": "arrakis", "aliases": {"foo": ["OFO/"], "bar": ["RBA/"],},},
{"name": "oz", "aliases": {"foo": ["ooF/"], "bar": ["raB/"],}},
],
- "plugins": [{"origin": "local", "path": "sources", "sources": {"fetch_source": 0}}],
+ "plugins": [{"origin": "local", "path": "sources", "sources": ["fetch_source"]}],
}
return project
diff --git a/tests/frontend/project/plugins/randomelement.py b/tests/frontend/project/plugins/randomelement.py
index e9be98fc7..12afaaa6d 100644
--- a/tests/frontend/project/plugins/randomelement.py
+++ b/tests/frontend/project/plugins/randomelement.py
@@ -4,6 +4,9 @@ from buildstream import Element
class RandomElement(Element):
+
+ BST_MIN_VERSION = "2.0"
+
def configure(self, node):
pass
diff --git a/tests/frontend/project/sources/fetch_source.py b/tests/frontend/project/sources/fetch_source.py
index c62d1d29a..6078e5e5f 100644
--- a/tests/frontend/project/sources/fetch_source.py
+++ b/tests/frontend/project/sources/fetch_source.py
@@ -32,6 +32,9 @@ class FetchFetcher(SourceFetcher):
class FetchSource(Source):
+
+ BST_MIN_VERSION = "2.0"
+
# Read config to know which URLs to fetch
def configure(self, node):
self.original_urls = node.get_str_list("urls")
diff --git a/tests/frontend/push.py b/tests/frontend/push.py
index 362084372..970885784 100644
--- a/tests/frontend/push.py
+++ b/tests/frontend/push.py
@@ -641,7 +641,7 @@ def test_push_after_rebuild(cli, tmpdir, datafiles):
config={
"element-path": "elements",
"min-version": "2.0",
- "plugins": [{"origin": "local", "path": "plugins", "elements": {"randomelement": 0}}],
+ "plugins": [{"origin": "local", "path": "plugins", "elements": ["randomelement"]}],
},
)
diff --git a/tests/internals/pluginfactory.py b/tests/internals/pluginfactory.py
deleted file mode 100644
index 13b9d3aae..000000000
--- a/tests/internals/pluginfactory.py
+++ /dev/null
@@ -1,287 +0,0 @@
-# Pylint doesn't play well with fixtures and dependency injection from pytest
-# pylint: disable=redefined-outer-name
-
-import os
-import pytest
-
-from pluginbase import PluginBase
-from buildstream import Node
-from buildstream._elementfactory import ElementFactory
-from buildstream._sourcefactory import SourceFactory
-from buildstream._exceptions import PluginError
-
-DATA_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "pluginfactory",)
-
-
-# Simple fixture to create a PluginBase object that
-# we use for loading plugins.
-@pytest.fixture()
-def plugin_fixture():
- return {"base": PluginBase(package="buildstream.plugins")}
-
-
-##############################################################
-# Basics: test the fixture, test we can create the factories #
-##############################################################
-def test_fixture(plugin_fixture):
- assert isinstance(plugin_fixture["base"], PluginBase)
-
-
-def test_source_factory(plugin_fixture):
- factory = SourceFactory(plugin_fixture["base"])
- assert isinstance(factory, SourceFactory)
-
-
-def test_element_factory(plugin_fixture):
- factory = ElementFactory(plugin_fixture["base"])
- assert isinstance(factory, ElementFactory)
-
-
-##############################################################
-# Check that we can load custom sources & elements #
-##############################################################
-@pytest.mark.datafiles(os.path.join(DATA_DIR, "customsource"))
-def test_custom_source(plugin_fixture, datafiles):
- plugins = [
- Node.from_dict(
- {"origin": "local", "path": os.path.join(datafiles.dirname, datafiles.basename), "plugins": ["foo"]}
- )
- ]
- factory = SourceFactory(plugin_fixture["base"], plugin_origins=plugins)
- assert isinstance(factory, SourceFactory)
-
- foo_type, _ = factory.lookup("foo")
- assert foo_type.__name__ == "FooSource"
-
-
-@pytest.mark.datafiles(os.path.join(DATA_DIR, "customelement"))
-def test_custom_element(plugin_fixture, datafiles):
- plugins = [
- Node.from_dict(
- {"origin": "local", "path": os.path.join(datafiles.dirname, datafiles.basename), "plugins": ["foo"]}
- )
- ]
- factory = ElementFactory(plugin_fixture["base"], plugin_origins=plugins)
- assert isinstance(factory, ElementFactory)
-
- foo_type, _ = factory.lookup("foo")
- assert foo_type.__name__ == "FooElement"
-
-
-##############################################################
-# Check plugin loading failure modes #
-##############################################################
-def test_missing_source(plugin_fixture):
- factory = SourceFactory(plugin_fixture["base"])
- assert isinstance(factory, SourceFactory)
-
- # Test fails if PluginError is not raised
- with pytest.raises(PluginError):
- factory.lookup("foo")
-
-
-def test_missing_element(plugin_fixture):
- factory = ElementFactory(plugin_fixture["base"])
- assert isinstance(factory, ElementFactory)
-
- # Test fails if PluginError is not raised
- with pytest.raises(PluginError):
- factory.lookup("foo")
-
-
-# Load a factory with a plugin that returns a value instead of Source subclass
-@pytest.mark.datafiles(os.path.join(DATA_DIR, "notatype"))
-def test_source_notatype(plugin_fixture, datafiles):
- plugins = [
- Node.from_dict(
- {"origin": "local", "path": os.path.join(datafiles.dirname, datafiles.basename), "plugins": ["foo"]}
- )
- ]
- factory = SourceFactory(plugin_fixture["base"], plugin_origins=plugins)
- with pytest.raises(PluginError):
- factory.lookup("foo")
-
-
-# Load a factory with a plugin that returns a value instead of Element subclass
-@pytest.mark.datafiles(os.path.join(DATA_DIR, "notatype"))
-def test_element_notatype(plugin_fixture, datafiles):
- plugins = [
- Node.from_dict(
- {"origin": "local", "path": os.path.join(datafiles.dirname, datafiles.basename), "plugins": ["foo"]}
- )
- ]
- factory = ElementFactory(plugin_fixture["base"], plugin_origins=plugins)
- with pytest.raises(PluginError):
- factory.lookup("foo")
-
-
-# Load a factory with a plugin that returns a type
-# which is not a Source subclass
-@pytest.mark.datafiles(os.path.join(DATA_DIR, "wrongtype"))
-def test_source_wrongtype(plugin_fixture, datafiles):
- plugins = [
- Node.from_dict(
- {"origin": "local", "path": os.path.join(datafiles.dirname, datafiles.basename), "plugins": ["foo"]}
- )
- ]
- factory = SourceFactory(plugin_fixture["base"], plugin_origins=plugins)
- with pytest.raises(PluginError):
- factory.lookup("foo")
-
-
-# Load a factory with a plugin that returns a type
-# which is not a Element subclass
-@pytest.mark.datafiles(os.path.join(DATA_DIR, "wrongtype"))
-def test_element_wrongtype(plugin_fixture, datafiles):
- plugins = [
- Node.from_dict(
- {"origin": "local", "path": os.path.join(datafiles.dirname, datafiles.basename), "plugins": ["foo"]}
- )
- ]
- factory = ElementFactory(plugin_fixture["base"], plugin_origins=plugins)
- with pytest.raises(PluginError):
- factory.lookup("foo")
-
-
-# Load a factory with a plugin which fails to provide a setup() function
-@pytest.mark.datafiles(os.path.join(DATA_DIR, "nosetup"))
-def test_source_missing_setup(plugin_fixture, datafiles):
- plugins = [
- Node.from_dict(
- {"origin": "local", "path": os.path.join(datafiles.dirname, datafiles.basename), "plugins": ["foo"]}
- )
- ]
- factory = SourceFactory(plugin_fixture["base"], plugin_origins=plugins)
- with pytest.raises(PluginError):
- factory.lookup("foo")
-
-
-# Load a factory with a plugin which fails to provide a setup() function
-@pytest.mark.datafiles(os.path.join(DATA_DIR, "nosetup"))
-def test_element_missing_setup(plugin_fixture, datafiles):
- plugins = [
- Node.from_dict(
- {"origin": "local", "path": os.path.join(datafiles.dirname, datafiles.basename), "plugins": ["foo"]}
- )
- ]
- factory = ElementFactory(plugin_fixture["base"], plugin_origins=plugins)
- with pytest.raises(PluginError):
- factory.lookup("foo")
-
-
-# Load a factory with a plugin which provides a setup symbol
-# that is not a function
-@pytest.mark.datafiles(os.path.join(DATA_DIR, "badsetup"))
-def test_source_bad_setup(plugin_fixture, datafiles):
- plugins = [
- Node.from_dict(
- {"origin": "local", "path": os.path.join(datafiles.dirname, datafiles.basename), "plugins": ["foo"]}
- )
- ]
- factory = SourceFactory(plugin_fixture["base"], plugin_origins=plugins)
- with pytest.raises(PluginError):
- factory.lookup("foo")
-
-
-# Load a factory with a plugin which provides a setup symbol
-# that is not a function
-@pytest.mark.datafiles(os.path.join(DATA_DIR, "badsetup"))
-def test_element_bad_setup(plugin_fixture, datafiles):
- plugins = [
- Node.from_dict(
- {"origin": "local", "path": os.path.join(datafiles.dirname, datafiles.basename), "plugins": ["foo"]}
- )
- ]
- factory = ElementFactory(plugin_fixture["base"], plugin_origins=plugins)
- with pytest.raises(PluginError):
- factory.lookup("foo")
-
-
-# Load a factory with a plugin which requires an absurdly
-# high version of buildstream
-@pytest.mark.datafiles(os.path.join(DATA_DIR, "badversionsource"))
-def test_source_badversion(plugin_fixture, datafiles):
- plugins = [
- Node.from_dict(
- {"origin": "local", "path": os.path.join(datafiles.dirname, datafiles.basename), "plugins": ["foo"]}
- )
- ]
- factory = SourceFactory(plugin_fixture["base"], plugin_origins=plugins)
- with pytest.raises(PluginError):
- factory.lookup("foo")
-
-
-# Load a factory with a plugin which requires an absurdly
-# high version of buildstream
-@pytest.mark.datafiles(os.path.join(DATA_DIR, "badversionelement"))
-def test_element_badversion(plugin_fixture, datafiles):
- plugins = [
- Node.from_dict(
- {"origin": "local", "path": os.path.join(datafiles.dirname, datafiles.basename), "plugins": ["foo"]}
- )
- ]
- factory = ElementFactory(plugin_fixture["base"], plugin_origins=plugins)
- with pytest.raises(PluginError):
- factory.lookup("foo")
-
-
-##############################################################
-# Check we can load different contexts of plugin #
-##############################################################
-
-# Load two factories, both of which define a different 'foo' plugin
-@pytest.mark.datafiles(DATA_DIR)
-def test_source_multicontext(plugin_fixture, datafiles):
- plugins1 = Node.from_dict(
- {
- "origin": "local",
- "path": os.path.join(datafiles.dirname, datafiles.basename, "customsource"),
- "plugins": ["foo"],
- }
- )
- plugins2 = Node.from_dict(
- {
- "origin": "local",
- "path": os.path.join(datafiles.dirname, datafiles.basename, "anothersource"),
- "plugins": ["foo"],
- }
- )
-
- factory1 = SourceFactory(plugin_fixture["base"], plugin_origins=[plugins1])
- factory2 = SourceFactory(plugin_fixture["base"], plugin_origins=[plugins2])
- assert isinstance(factory1, SourceFactory)
- assert isinstance(factory2, SourceFactory)
-
- foo_type1, _ = factory1.lookup("foo")
- foo_type2, _ = factory2.lookup("foo")
- assert foo_type1.__name__ == "FooSource"
- assert foo_type2.__name__ == "AnotherFooSource"
-
-
-# Load two factories, both of which define a different 'foo' plugin
-@pytest.mark.datafiles(DATA_DIR)
-def test_element_multicontext(plugin_fixture, datafiles):
- plugins1 = Node.from_dict(
- {
- "origin": "local",
- "path": os.path.join(datafiles.dirname, datafiles.basename, "customelement"),
- "plugins": ["foo"],
- }
- )
- plugins2 = Node.from_dict(
- {
- "origin": "local",
- "path": os.path.join(datafiles.dirname, datafiles.basename, "anotherelement"),
- "plugins": ["foo"],
- }
- )
-
- factory1 = ElementFactory(plugin_fixture["base"], plugin_origins=[plugins1])
- factory2 = ElementFactory(plugin_fixture["base"], plugin_origins=[plugins2])
- assert isinstance(factory1, ElementFactory)
- assert isinstance(factory2, ElementFactory)
-
- foo_type1, _ = factory1.lookup("foo")
- foo_type2, _ = factory2.lookup("foo")
- assert foo_type1.__name__ == "FooElement"
- assert foo_type2.__name__ == "AnotherFooElement"
diff --git a/tests/internals/pluginfactory/anotherelement/__init__.py b/tests/internals/pluginfactory/anotherelement/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/tests/internals/pluginfactory/anotherelement/__init__.py
+++ /dev/null
diff --git a/tests/internals/pluginfactory/anotherelement/foo.py b/tests/internals/pluginfactory/anotherelement/foo.py
deleted file mode 100644
index 2e067a94f..000000000
--- a/tests/internals/pluginfactory/anotherelement/foo.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from buildstream import Element
-
-
-class AnotherFooElement(Element):
- pass
-
-
-def setup():
- return AnotherFooElement
diff --git a/tests/internals/pluginfactory/anothersource/__init__.py b/tests/internals/pluginfactory/anothersource/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/tests/internals/pluginfactory/anothersource/__init__.py
+++ /dev/null
diff --git a/tests/internals/pluginfactory/anothersource/foo.py b/tests/internals/pluginfactory/anothersource/foo.py
deleted file mode 100644
index 4675b965f..000000000
--- a/tests/internals/pluginfactory/anothersource/foo.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from buildstream import Source
-
-
-class AnotherFooSource(Source):
- pass
-
-
-def setup():
- return AnotherFooSource
diff --git a/tests/internals/pluginfactory/badsetup/__init__.py b/tests/internals/pluginfactory/badsetup/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/tests/internals/pluginfactory/badsetup/__init__.py
+++ /dev/null
diff --git a/tests/internals/pluginfactory/badsetup/foo.py b/tests/internals/pluginfactory/badsetup/foo.py
deleted file mode 100644
index 145f2577b..000000000
--- a/tests/internals/pluginfactory/badsetup/foo.py
+++ /dev/null
@@ -1,6 +0,0 @@
-# A plugin is supposed to define a setup function
-# which returns the type that the plugin provides
-#
-# This plugin provides a setup() symbol that is
-# not even a function
-setup = 5
diff --git a/tests/internals/pluginfactory/badversionelement/__init__.py b/tests/internals/pluginfactory/badversionelement/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/tests/internals/pluginfactory/badversionelement/__init__.py
+++ /dev/null
diff --git a/tests/internals/pluginfactory/badversionelement/foo.py b/tests/internals/pluginfactory/badversionelement/foo.py
deleted file mode 100644
index 2a8b12abe..000000000
--- a/tests/internals/pluginfactory/badversionelement/foo.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from buildstream import Element
-
-
-class FooElement(Element):
-
- # We have a little while until we have to manually modify this
- BST_REQUIRED_VERSION_MAJOR = 5000
-
-
-def setup():
- return FooElement
diff --git a/tests/internals/pluginfactory/badversionsource/__init__.py b/tests/internals/pluginfactory/badversionsource/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/tests/internals/pluginfactory/badversionsource/__init__.py
+++ /dev/null
diff --git a/tests/internals/pluginfactory/badversionsource/foo.py b/tests/internals/pluginfactory/badversionsource/foo.py
deleted file mode 100644
index 23333a9d8..000000000
--- a/tests/internals/pluginfactory/badversionsource/foo.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from buildstream import Source
-
-
-class FooSource(Source):
-
- # We have a little while until we have to manually modify this
- BST_REQUIRED_VERSION_MAJOR = 5000
-
-
-def setup():
- return FooSource
diff --git a/tests/internals/pluginfactory/customelement/__init__.py b/tests/internals/pluginfactory/customelement/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/tests/internals/pluginfactory/customelement/__init__.py
+++ /dev/null
diff --git a/tests/internals/pluginfactory/customelement/foo.py b/tests/internals/pluginfactory/customelement/foo.py
deleted file mode 100644
index 260de8b27..000000000
--- a/tests/internals/pluginfactory/customelement/foo.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from buildstream import Element
-
-
-class FooElement(Element):
- pass
-
-
-def setup():
- return FooElement
diff --git a/tests/internals/pluginfactory/customsource/__init__.py b/tests/internals/pluginfactory/customsource/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/tests/internals/pluginfactory/customsource/__init__.py
+++ /dev/null
diff --git a/tests/internals/pluginfactory/customsource/foo.py b/tests/internals/pluginfactory/customsource/foo.py
deleted file mode 100644
index de78a00ce..000000000
--- a/tests/internals/pluginfactory/customsource/foo.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from buildstream import Source
-
-
-class FooSource(Source):
- pass
-
-
-def setup():
- return FooSource
diff --git a/tests/internals/pluginfactory/nosetup/__init__.py b/tests/internals/pluginfactory/nosetup/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/tests/internals/pluginfactory/nosetup/__init__.py
+++ /dev/null
diff --git a/tests/internals/pluginfactory/notatype/__init__.py b/tests/internals/pluginfactory/notatype/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/tests/internals/pluginfactory/notatype/__init__.py
+++ /dev/null
diff --git a/tests/internals/pluginfactory/notatype/foo.py b/tests/internals/pluginfactory/notatype/foo.py
deleted file mode 100644
index 311a4fb32..000000000
--- a/tests/internals/pluginfactory/notatype/foo.py
+++ /dev/null
@@ -1,6 +0,0 @@
-# Plugins are supposed to return a subclass type
-# of Source or Element, depending on plugin type.
-
-
-def setup():
- return 5
diff --git a/tests/internals/pluginfactory/wrongtype/__init__.py b/tests/internals/pluginfactory/wrongtype/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/tests/internals/pluginfactory/wrongtype/__init__.py
+++ /dev/null
diff --git a/tests/internals/pluginfactory/wrongtype/foo.py b/tests/internals/pluginfactory/wrongtype/foo.py
deleted file mode 100644
index 37d9f6bfe..000000000
--- a/tests/internals/pluginfactory/wrongtype/foo.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Plugins are supposed to return a subclass type
-# of Source or Element, depending on plugin type.
-#
-# This one fails the requirement
-
-
-class Foo:
- pass
-
-
-def setup():
- return Foo
diff --git a/tests/internals/pluginloading.py b/tests/internals/pluginloading.py
index 0685b09da..1f4446541 100644
--- a/tests/internals/pluginloading.py
+++ b/tests/internals/pluginloading.py
@@ -3,8 +3,6 @@ import os
import pytest
from buildstream._project import Project
-from buildstream._exceptions import LoadError
-from buildstream.exceptions import LoadErrorReason
from buildstream._pipeline import Pipeline
from tests.testutils import dummy_context
@@ -38,23 +36,3 @@ def test_customelement(datafiles, tmpdir):
basedir = str(datafiles)
with create_pipeline(tmpdir, basedir, "simple.bst") as targets:
assert targets[0].get_kind() == "foo"
-
-
-@pytest.mark.datafiles(os.path.join(DATA_DIR, "badversionsource"))
-def test_badversionsource(datafiles, tmpdir):
- basedir = str(datafiles)
-
- with pytest.raises(LoadError) as exc, create_pipeline(tmpdir, basedir, "simple.bst"):
- pass
-
- assert exc.value.reason == LoadErrorReason.UNSUPPORTED_PLUGIN
-
-
-@pytest.mark.datafiles(os.path.join(DATA_DIR, "badversionelement"))
-def test_badversionelement(datafiles, tmpdir):
- basedir = str(datafiles)
-
- with pytest.raises(LoadError) as exc, create_pipeline(tmpdir, basedir, "simple.bst"):
- pass
-
- assert exc.value.reason == LoadErrorReason.UNSUPPORTED_PLUGIN
diff --git a/tests/internals/pluginloading/badversionelement/customelements/__init__.py b/tests/internals/pluginloading/badversionelement/customelements/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/tests/internals/pluginloading/badversionelement/customelements/__init__.py
+++ /dev/null
diff --git a/tests/internals/pluginloading/badversionelement/customelements/foo.py b/tests/internals/pluginloading/badversionelement/customelements/foo.py
deleted file mode 100644
index 75536e87f..000000000
--- a/tests/internals/pluginloading/badversionelement/customelements/foo.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from buildstream import Element
-
-
-class FooElement(Element):
-
- BST_FORMAT_VERSION = 5
-
- def preflight(self):
- pass
-
- def configure(self, node):
- pass
-
- def get_unique_key(self):
- return {}
-
-
-def setup():
- return FooElement
diff --git a/tests/internals/pluginloading/badversionelement/elements/simple.bst b/tests/internals/pluginloading/badversionelement/elements/simple.bst
deleted file mode 100644
index f949dc5b5..000000000
--- a/tests/internals/pluginloading/badversionelement/elements/simple.bst
+++ /dev/null
@@ -1,4 +0,0 @@
-kind: foo
-description: Custom foo element
-config:
- some: thing
diff --git a/tests/internals/pluginloading/badversionelement/project.conf b/tests/internals/pluginloading/badversionelement/project.conf
deleted file mode 100644
index bff73e251..000000000
--- a/tests/internals/pluginloading/badversionelement/project.conf
+++ /dev/null
@@ -1,10 +0,0 @@
-name: pony
-min-version: 2.0
-element-path: elements
-
-plugins:
-- origin: local
- path: customelements
- elements:
- # We provided bar at version 5, should be a conflict.
- foo: 10
diff --git a/tests/internals/pluginloading/badversionsource/customsources/__init__.py b/tests/internals/pluginloading/badversionsource/customsources/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/tests/internals/pluginloading/badversionsource/customsources/__init__.py
+++ /dev/null
diff --git a/tests/internals/pluginloading/badversionsource/customsources/foo.py b/tests/internals/pluginloading/badversionsource/customsources/foo.py
deleted file mode 100644
index 628f99b29..000000000
--- a/tests/internals/pluginloading/badversionsource/customsources/foo.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from buildstream import Source
-
-
-class BarSource(Source):
-
- BST_FORMAT_VERSION = 5
-
- def preflight(self):
- pass
-
- def configure(self, node):
- pass
-
-
-def setup():
- return BarSource
diff --git a/tests/internals/pluginloading/badversionsource/elements/simple.bst b/tests/internals/pluginloading/badversionsource/elements/simple.bst
deleted file mode 100644
index 7e0cc43b7..000000000
--- a/tests/internals/pluginloading/badversionsource/elements/simple.bst
+++ /dev/null
@@ -1,6 +0,0 @@
-kind: autotools
-description: Custom foo source
-sources:
-- kind: foo
- ref: 1.2.3
- uri: http://ponyland.com
diff --git a/tests/internals/pluginloading/badversionsource/project.conf b/tests/internals/pluginloading/badversionsource/project.conf
deleted file mode 100644
index cd5b2dc82..000000000
--- a/tests/internals/pluginloading/badversionsource/project.conf
+++ /dev/null
@@ -1,10 +0,0 @@
-name: pony
-min-version: 2.0
-element-path: elements
-
-plugins:
-- origin: local
- path: customsources
- sources:
- # We provided bar at version 5, should be a conflict.
- foo: 10
diff --git a/tests/internals/pluginloading/customelement/pluginelements/foo.py b/tests/internals/pluginloading/customelement/pluginelements/foo.py
index c6a85a5b1..bdb6c8982 100644
--- a/tests/internals/pluginloading/customelement/pluginelements/foo.py
+++ b/tests/internals/pluginloading/customelement/pluginelements/foo.py
@@ -2,6 +2,9 @@ from buildstream import Element
class FooElement(Element):
+
+ BST_MIN_VERSION = "2.0"
+
def preflight(self):
pass
diff --git a/tests/internals/pluginloading/customelement/project.conf b/tests/internals/pluginloading/customelement/project.conf
index 6a33cc504..2619bdf82 100644
--- a/tests/internals/pluginloading/customelement/project.conf
+++ b/tests/internals/pluginloading/customelement/project.conf
@@ -5,4 +5,4 @@ plugins:
- origin: local
path: pluginelements
elements:
- foo: 0
+ - foo
diff --git a/tests/internals/pluginloading/customsource/pluginsources/foo.py b/tests/internals/pluginloading/customsource/pluginsources/foo.py
index fce5239b1..c5229f3e2 100644
--- a/tests/internals/pluginloading/customsource/pluginsources/foo.py
+++ b/tests/internals/pluginloading/customsource/pluginsources/foo.py
@@ -2,6 +2,9 @@ from buildstream import Source
class FooSource(Source):
+
+ BST_MIN_VERSION = "2.0"
+
def preflight(self):
pass
diff --git a/tests/internals/pluginloading/customsource/project.conf b/tests/internals/pluginloading/customsource/project.conf
index 87d9b5d09..5cb6da537 100644
--- a/tests/internals/pluginloading/customsource/project.conf
+++ b/tests/internals/pluginloading/customsource/project.conf
@@ -5,4 +5,4 @@ plugins:
- origin: local
path: pluginsources
sources:
- foo: 0
+ - foo
diff --git a/tests/plugins/deprecationwarnings/deprecationwarnings.py b/tests/plugins/deprecationwarnings.py
index 628faea68..a4da3ea72 100644
--- a/tests/plugins/deprecationwarnings/deprecationwarnings.py
+++ b/tests/plugins/deprecationwarnings.py
@@ -8,7 +8,7 @@ import pytest
from buildstream.testing import cli # pylint: disable=unused-import
-DATA_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "project")
+DATA_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "deprecationwarnings")
_DEPRECATION_MESSAGE = "Here is some detail."
_DEPRECATION_WARNING = "Using deprecated plugin deprecated_plugin: {}".format(_DEPRECATION_MESSAGE)
diff --git a/tests/plugins/deprecationwarnings/__init__.py b/tests/plugins/deprecationwarnings/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/tests/plugins/deprecationwarnings/__init__.py
+++ /dev/null
diff --git a/tests/plugins/deprecationwarnings/project/elements/deprecated.bst b/tests/plugins/deprecationwarnings/elements/deprecated.bst
index e80bd91cd..e80bd91cd 100644
--- a/tests/plugins/deprecationwarnings/project/elements/deprecated.bst
+++ b/tests/plugins/deprecationwarnings/elements/deprecated.bst
diff --git a/tests/plugins/deprecationwarnings/project/plugins/elements/deprecated_plugin.py b/tests/plugins/deprecationwarnings/plugins/elements/deprecated_plugin.py
index 1badf59af..244009764 100644
--- a/tests/plugins/deprecationwarnings/project/plugins/elements/deprecated_plugin.py
+++ b/tests/plugins/deprecationwarnings/plugins/elements/deprecated_plugin.py
@@ -2,6 +2,7 @@ from buildstream import BuildElement
class DeprecatedPlugin(BuildElement):
+ BST_MIN_VERSION = "2.0"
BST_PLUGIN_DEPRECATED = True
BST_PLUGIN_DEPRECATION_MESSAGE = "Here is some detail."
diff --git a/tests/plugins/deprecationwarnings/project/plugins/elements/deprecated_plugin.yaml b/tests/plugins/deprecationwarnings/plugins/elements/deprecated_plugin.yaml
index 1c07cd8b2..1c07cd8b2 100644
--- a/tests/plugins/deprecationwarnings/project/plugins/elements/deprecated_plugin.yaml
+++ b/tests/plugins/deprecationwarnings/plugins/elements/deprecated_plugin.yaml
diff --git a/tests/plugins/deprecationwarnings/project/project.conf b/tests/plugins/deprecationwarnings/project.conf
index 8a2536cab..9e03afe0a 100644
--- a/tests/plugins/deprecationwarnings/project/project.conf
+++ b/tests/plugins/deprecationwarnings/project.conf
@@ -12,4 +12,4 @@ plugins:
- origin: local
path: plugins/elements
elements:
- deprecated_plugin: 0
+ - deprecated_plugin
diff --git a/tests/plugins/loading.py b/tests/plugins/loading.py
new file mode 100644
index 000000000..a368e9952
--- /dev/null
+++ b/tests/plugins/loading.py
@@ -0,0 +1,202 @@
+# Pylint doesn't play well with fixtures and dependency injection from pytest
+# pylint: disable=redefined-outer-name
+
+#
+# This test case tests the failure modes of loading a plugin
+# after it has already been discovered via it's origin.
+#
+
+import os
+import pytest
+
+from buildstream.exceptions import ErrorDomain
+from buildstream.testing import cli # pylint: disable=unused-import
+from buildstream import _yaml
+
+
+DATA_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "loading")
+
+
+def update_project(project_path, updated_configuration):
+ project_conf_path = os.path.join(project_path, "project.conf")
+ project_conf = _yaml.roundtrip_load(project_conf_path)
+
+ project_conf.update(updated_configuration)
+
+ _yaml.roundtrip_dump(project_conf, project_conf_path)
+
+
+# Sets up the element.bst file so that it requires a source
+# or element plugin.
+#
+def setup_element(project_path, plugin_type, plugin_name):
+ element_dir = os.path.join(project_path, "elements")
+ element_path = os.path.join(element_dir, "element.bst")
+ os.makedirs(element_dir, exist_ok=True)
+
+ if plugin_type == "elements":
+ element = {"kind": plugin_name}
+ else:
+ element = {"kind": "manual", "sources": [{"kind": plugin_name}]}
+
+ _yaml.roundtrip_dump(element, element_path)
+
+
+####################################################
+# Tests #
+####################################################
+@pytest.mark.datafiles(DATA_DIR)
+@pytest.mark.parametrize("plugin_type", [("elements"), ("sources")])
+def test_nosetup(cli, datafiles, plugin_type):
+ project = str(datafiles)
+
+ update_project(project, {"plugins": [{"origin": "local", "path": "plugins/nosetup", plugin_type: ["nosetup"]}]})
+ setup_element(project, plugin_type, "nosetup")
+
+ result = cli.run(project=project, args=["show", "element.bst"])
+ result.assert_main_error(ErrorDomain.PLUGIN, "missing-setup-function")
+
+
+@pytest.mark.datafiles(DATA_DIR)
+@pytest.mark.parametrize("plugin_type", [("elements"), ("sources")])
+def test_setup_not_function(cli, datafiles, plugin_type):
+ project = str(datafiles)
+
+ update_project(
+ project,
+ {"plugins": [{"origin": "local", "path": "plugins/setupnotfunction", plugin_type: ["setupnotfunction"]}]},
+ )
+ setup_element(project, plugin_type, "setupnotfunction")
+
+ result = cli.run(project=project, args=["show", "element.bst"])
+ result.assert_main_error(ErrorDomain.PLUGIN, "setup-is-not-function")
+
+
+@pytest.mark.datafiles(DATA_DIR)
+@pytest.mark.parametrize("plugin_type", [("elements"), ("sources")])
+def test_setup_returns_not_type(cli, datafiles, plugin_type):
+ project = str(datafiles)
+
+ update_project(
+ project,
+ {
+ "plugins": [
+ {"origin": "local", "path": "plugins/setupreturnsnottype", plugin_type: ["setupreturnsnottype"]}
+ ]
+ },
+ )
+ setup_element(project, plugin_type, "setupreturnsnottype")
+
+ result = cli.run(project=project, args=["show", "element.bst"])
+ result.assert_main_error(ErrorDomain.PLUGIN, "setup-returns-not-type")
+
+
+@pytest.mark.datafiles(DATA_DIR)
+@pytest.mark.parametrize("plugin_type", [("elements"), ("sources")])
+def test_setup_returns_bad_type(cli, datafiles, plugin_type):
+ project = str(datafiles)
+
+ update_project(
+ project,
+ {
+ "plugins": [
+ {"origin": "local", "path": "plugins/setupreturnsbadtype", plugin_type: ["setupreturnsbadtype"]}
+ ]
+ },
+ )
+ setup_element(project, plugin_type, "setupreturnsbadtype")
+
+ result = cli.run(project=project, args=["show", "element.bst"])
+ result.assert_main_error(ErrorDomain.PLUGIN, "setup-returns-bad-type")
+
+
+@pytest.mark.datafiles(DATA_DIR)
+@pytest.mark.parametrize("plugin_type", [("elements"), ("sources")])
+def test_missing_min_version(cli, datafiles, plugin_type):
+ project = str(datafiles)
+
+ update_project(
+ project,
+ {
+ "plugins": [
+ {
+ "origin": "local",
+ "path": os.path.join("plugins", plugin_type, "nominversion"),
+ plugin_type: ["nominversion"],
+ }
+ ]
+ },
+ )
+ setup_element(project, plugin_type, "nominversion")
+
+ result = cli.run(project=project, args=["show", "element.bst"])
+ result.assert_main_error(ErrorDomain.PLUGIN, "missing-min-version")
+
+
+@pytest.mark.datafiles(DATA_DIR)
+@pytest.mark.parametrize("plugin_type", [("elements"), ("sources")])
+def test_malformed_min_version(cli, datafiles, plugin_type):
+ project = str(datafiles)
+
+ update_project(
+ project,
+ {
+ "plugins": [
+ {
+ "origin": "local",
+ "path": os.path.join("plugins", plugin_type, "malformedminversion"),
+ plugin_type: ["malformedminversion"],
+ }
+ ]
+ },
+ )
+ setup_element(project, plugin_type, "malformedminversion")
+
+ result = cli.run(project=project, args=["show", "element.bst"])
+ result.assert_main_error(ErrorDomain.PLUGIN, "malformed-min-version")
+
+
+@pytest.mark.datafiles(DATA_DIR)
+@pytest.mark.parametrize("plugin_type", [("elements"), ("sources")])
+def test_incompatible_major_version(cli, datafiles, plugin_type):
+ project = str(datafiles)
+
+ update_project(
+ project,
+ {
+ "plugins": [
+ {
+ "origin": "local",
+ "path": os.path.join("plugins", plugin_type, "incompatiblemajor"),
+ plugin_type: ["incompatiblemajor"],
+ }
+ ]
+ },
+ )
+ setup_element(project, plugin_type, "incompatiblemajor")
+
+ result = cli.run(project=project, args=["show", "element.bst"])
+ result.assert_main_error(ErrorDomain.PLUGIN, "incompatible-major-version")
+
+
+@pytest.mark.datafiles(DATA_DIR)
+@pytest.mark.parametrize("plugin_type", [("elements"), ("sources")])
+def test_incompatible_minor_version(cli, datafiles, plugin_type):
+ project = str(datafiles)
+
+ update_project(
+ project,
+ {
+ "plugins": [
+ {
+ "origin": "local",
+ "path": os.path.join("plugins", plugin_type, "incompatibleminor"),
+ plugin_type: ["incompatibleminor"],
+ }
+ ]
+ },
+ )
+ setup_element(project, plugin_type, "incompatibleminor")
+
+ result = cli.run(project=project, args=["show", "element.bst"])
+ result.assert_main_error(ErrorDomain.PLUGIN, "incompatible-minor-version")
diff --git a/tests/plugins/loading/plugins/elements/incompatiblemajor/incompatiblemajor.py b/tests/plugins/loading/plugins/elements/incompatiblemajor/incompatiblemajor.py
new file mode 100644
index 000000000..a0ea59309
--- /dev/null
+++ b/tests/plugins/loading/plugins/elements/incompatiblemajor/incompatiblemajor.py
@@ -0,0 +1,10 @@
+from buildstream import Element
+
+
+class IncompatibleMajor(Element):
+
+ BST_MIN_VERSION = "1.0"
+
+
+def setup():
+ return IncompatibleMajor
diff --git a/tests/plugins/loading/plugins/elements/incompatibleminor/incompatibleminor.py b/tests/plugins/loading/plugins/elements/incompatibleminor/incompatibleminor.py
new file mode 100644
index 000000000..d9967caaa
--- /dev/null
+++ b/tests/plugins/loading/plugins/elements/incompatibleminor/incompatibleminor.py
@@ -0,0 +1,10 @@
+from buildstream import Element
+
+
+class IncompatibleMinor(Element):
+
+ BST_MIN_VERSION = "2.1000"
+
+
+def setup():
+ return IncompatibleMinor
diff --git a/tests/plugins/loading/plugins/elements/malformedminversion/malformedminversion.py b/tests/plugins/loading/plugins/elements/malformedminversion/malformedminversion.py
new file mode 100644
index 000000000..5f96c1897
--- /dev/null
+++ b/tests/plugins/loading/plugins/elements/malformedminversion/malformedminversion.py
@@ -0,0 +1,11 @@
+# Plugins are required to specify the BST_MIN_VERSION
+from buildstream import Element
+
+
+class MalformedMinVersion(Element):
+
+ BST_MIN_VERSION = "1.pony"
+
+
+def setup():
+ return MalformedMinVersion
diff --git a/tests/plugins/loading/plugins/elements/nominversion/nominversion.py b/tests/plugins/loading/plugins/elements/nominversion/nominversion.py
new file mode 100644
index 000000000..e3f5b0cb6
--- /dev/null
+++ b/tests/plugins/loading/plugins/elements/nominversion/nominversion.py
@@ -0,0 +1,10 @@
+# Plugins are required to specify the BST_MIN_VERSION
+from buildstream import Element
+
+
+class NoMinVersion(Element):
+ pass
+
+
+def setup():
+ return NoMinVersion
diff --git a/tests/internals/pluginfactory/nosetup/foo.py b/tests/plugins/loading/plugins/nosetup/nosetup.py
index 0b5a4fa7e..0b5a4fa7e 100644
--- a/tests/internals/pluginfactory/nosetup/foo.py
+++ b/tests/plugins/loading/plugins/nosetup/nosetup.py
diff --git a/tests/plugins/loading/plugins/setupnotfunction/setupnotfunction.py b/tests/plugins/loading/plugins/setupnotfunction/setupnotfunction.py
new file mode 100644
index 000000000..1272f4ee0
--- /dev/null
+++ b/tests/plugins/loading/plugins/setupnotfunction/setupnotfunction.py
@@ -0,0 +1,6 @@
+# A plugin's setup symbol is supposed to be a function
+# which returns the plugin type.
+#
+# This plugin's setup symbol is not such a function.
+
+setup = 9
diff --git a/tests/plugins/loading/plugins/setupreturnsbadtype/setupreturnsbadtype.py b/tests/plugins/loading/plugins/setupreturnsbadtype/setupreturnsbadtype.py
new file mode 100644
index 000000000..25795c06b
--- /dev/null
+++ b/tests/plugins/loading/plugins/setupreturnsbadtype/setupreturnsbadtype.py
@@ -0,0 +1,15 @@
+# A plugin's setup symbol is supposed to be a function
+# which returns the plugin type, which should be a subclass
+# of Source or Element depending on the plugin type.
+#
+# This plugin's setup function returns a different kind
+# of type.
+
+
+class Pony:
+ def __init__(self):
+ self.pony = 12
+
+
+def setup():
+ return Pony
diff --git a/tests/plugins/loading/plugins/setupreturnsnottype/setupreturnsnottype.py b/tests/plugins/loading/plugins/setupreturnsnottype/setupreturnsnottype.py
new file mode 100644
index 000000000..d47367ea9
--- /dev/null
+++ b/tests/plugins/loading/plugins/setupreturnsnottype/setupreturnsnottype.py
@@ -0,0 +1,8 @@
+# A plugin's setup symbol is supposed to be a function
+# which returns the plugin type.
+#
+# This plugin's setup function returns a number instead
+
+
+def setup():
+ return 5
diff --git a/tests/plugins/loading/plugins/sources/incompatiblemajor/incompatiblemajor.py b/tests/plugins/loading/plugins/sources/incompatiblemajor/incompatiblemajor.py
new file mode 100644
index 000000000..f2d088b77
--- /dev/null
+++ b/tests/plugins/loading/plugins/sources/incompatiblemajor/incompatiblemajor.py
@@ -0,0 +1,10 @@
+from buildstream import Source
+
+
+class IncompatibleMajor(Source):
+
+ BST_MIN_VERSION = "1.0"
+
+
+def setup():
+ return IncompatibleMajor
diff --git a/tests/plugins/loading/plugins/sources/incompatibleminor/incompatibleminor.py b/tests/plugins/loading/plugins/sources/incompatibleminor/incompatibleminor.py
new file mode 100644
index 000000000..2282534ae
--- /dev/null
+++ b/tests/plugins/loading/plugins/sources/incompatibleminor/incompatibleminor.py
@@ -0,0 +1,10 @@
+from buildstream import Source
+
+
+class IncompatibleMinor(Source):
+
+ BST_MIN_VERSION = "2.1000"
+
+
+def setup():
+ return IncompatibleMinor
diff --git a/tests/plugins/loading/plugins/sources/malformedminversion/malformedminversion.py b/tests/plugins/loading/plugins/sources/malformedminversion/malformedminversion.py
new file mode 100644
index 000000000..90474597c
--- /dev/null
+++ b/tests/plugins/loading/plugins/sources/malformedminversion/malformedminversion.py
@@ -0,0 +1,11 @@
+# Plugins are required to specify the BST_MIN_VERSION
+from buildstream import Source
+
+
+class MalformedMinVersion(Source):
+
+ BST_MIN_VERSION = "1.pony"
+
+
+def setup():
+ return MalformedMinVersion
diff --git a/tests/plugins/loading/plugins/sources/nominversion/nominversion.py b/tests/plugins/loading/plugins/sources/nominversion/nominversion.py
new file mode 100644
index 000000000..12cdfa296
--- /dev/null
+++ b/tests/plugins/loading/plugins/sources/nominversion/nominversion.py
@@ -0,0 +1,10 @@
+# Plugins are required to specify the BST_MIN_VERSION
+from buildstream import Source
+
+
+class NoMinVersion(Source):
+ pass
+
+
+def setup():
+ return NoMinVersion
diff --git a/tests/plugins/loading/project.conf b/tests/plugins/loading/project.conf
new file mode 100644
index 000000000..738051af9
--- /dev/null
+++ b/tests/plugins/loading/project.conf
@@ -0,0 +1,8 @@
+# This project.conf gets rewritten for each plugin loading test
+name: test
+
+# Required BuildStream version
+min-version: 2.0
+
+# Subdirectory where elements are stored
+element-path: elements
diff --git a/tests/sourcecache/project/plugins/elements/always_fail.py b/tests/sourcecache/project/plugins/elements/always_fail.py
index 43dba5626..bc3ed57b6 100644
--- a/tests/sourcecache/project/plugins/elements/always_fail.py
+++ b/tests/sourcecache/project/plugins/elements/always_fail.py
@@ -23,6 +23,9 @@ from buildstream.buildelement import BuildElement
class AlwaysFail(BuildElement):
+
+ BST_MIN_VERSION = "2.0"
+
def assemble(self, sandbox):
raise ElementError("Always fails")
diff --git a/tests/sourcecache/project/project.conf b/tests/sourcecache/project/project.conf
index dde417f71..e3635e8a7 100644
--- a/tests/sourcecache/project/project.conf
+++ b/tests/sourcecache/project/project.conf
@@ -9,4 +9,4 @@ plugins:
- origin: local
path: plugins/elements
elements:
- always_fail: 0 \ No newline at end of file
+ - always_fail
diff --git a/tests/sources/no-fetch-cached/plugins/sources/always_cached.py b/tests/sources/no-fetch-cached/plugins/sources/always_cached.py
index aef13279b..b5dfd772c 100644
--- a/tests/sources/no-fetch-cached/plugins/sources/always_cached.py
+++ b/tests/sources/no-fetch-cached/plugins/sources/always_cached.py
@@ -11,6 +11,8 @@ from buildstream import Source
class AlwaysCachedSource(Source):
+ BST_MIN_VERSION = "2.0"
+
def configure(self, node):
pass
diff --git a/tests/sources/no-fetch-cached/project.conf b/tests/sources/no-fetch-cached/project.conf
index eeb00d432..ef5b4a3b9 100644
--- a/tests/sources/no-fetch-cached/project.conf
+++ b/tests/sources/no-fetch-cached/project.conf
@@ -6,4 +6,4 @@ plugins:
- origin: local
path: plugins/sources
sources:
- always_cached: 0
+ - always_cached
diff --git a/tests/sources/previous_source_access/plugins/sources/foo_transform.py b/tests/sources/previous_source_access/plugins/sources/foo_transform.py
index dbc44c8aa..15fef43f8 100644
--- a/tests/sources/previous_source_access/plugins/sources/foo_transform.py
+++ b/tests/sources/previous_source_access/plugins/sources/foo_transform.py
@@ -14,6 +14,7 @@ from buildstream import Source, SourceError, utils
class FooTransformSource(Source):
+ BST_MIN_VERSION = "2.0"
# We need access to previous both at track time and fetch time
BST_REQUIRES_PREVIOUS_SOURCES_TRACK = True
diff --git a/tests/sources/previous_source_access/project.conf b/tests/sources/previous_source_access/project.conf
index 2d3bb1fb2..b08df35f0 100644
--- a/tests/sources/previous_source_access/project.conf
+++ b/tests/sources/previous_source_access/project.conf
@@ -11,4 +11,4 @@ plugins:
- origin: local
path: plugins/sources
sources:
- foo_transform: 0
+ - foo_transform
diff --git a/tests/sources/project_key_test/plugins/sources/key-test.py b/tests/sources/project_key_test/plugins/sources/key-test.py
index 88a211738..046034804 100644
--- a/tests/sources/project_key_test/plugins/sources/key-test.py
+++ b/tests/sources/project_key_test/plugins/sources/key-test.py
@@ -7,6 +7,8 @@ class KeyTest(Source):
""" This plugin should fail if get_unique_key is called before track
"""
+ BST_MIN_VERSION = "2.0"
+
def preflight(self):
pass
diff --git a/tests/sources/project_key_test/project.conf b/tests/sources/project_key_test/project.conf
index fb9ba1f88..6b82d4055 100644
--- a/tests/sources/project_key_test/project.conf
+++ b/tests/sources/project_key_test/project.conf
@@ -8,4 +8,4 @@ plugins:
- origin: local
path: plugins/sources
sources:
- key-test: 0 \ No newline at end of file
+ - key-test
diff --git a/tox.ini b/tox.ini
index fd9017db2..94e4048ce 100644
--- a/tox.ini
+++ b/tox.ini
@@ -8,7 +8,7 @@ isolated_build = true
# Configuration variables to share across environments
[config]
-BST_PLUGINS_EXPERIMENTAL_VERSION = 1.93.1.1
+BST_PLUGINS_EXPERIMENTAL_VERSION = 1.93.2
#
# Defaults for all environments