diff options
author | Tristan Van Berkom <tristan.vanberkom@codethink.co.uk> | 2020-04-28 19:23:31 +0900 |
---|---|---|
committer | Tristan Van Berkom <tristan.vanberkom@codethink.co.uk> | 2020-04-29 16:24:59 +0900 |
commit | a311a14f4b0a649b5f872ab020885b0a1d6e09d1 (patch) | |
tree | c94ddb9ff24108b72d4e0c2e8902bf24d6702b95 /src | |
parent | b3556a3284708b904f20586d4636c31a91106809 (diff) | |
download | buildstream-a311a14f4b0a649b5f872ab020885b0a1d6e09d1.tar.gz |
plugin.py/pluginfactory.py: Implementing BST_MIN_VERSION
The BST_MIN_VERSION guards assert that the BuildStream core which
loaded the plugin is compatible with the plugin itself.
This commit adds BST_MIN_VERSION to the base plugin.py with documentation
informing Plugin authors how to set the minimum version, and also adds
the assertions at plugin loading time in pluginfactory.py.
This commit also:
* Adds the BST_MIN_VERSION specification to all current core plugins
* Adds the BST_MIN_VERSION specification to plugins used in test cases
Diffstat (limited to 'src')
21 files changed, 119 insertions, 3 deletions
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/pluginfactory.py b/src/buildstream/_pluginfactory/pluginfactory.py index 7e5ae2db0..27321c62f 100644 --- a/src/buildstream/_pluginfactory/pluginfactory.py +++ b/src/buildstream/_pluginfactory/pluginfactory.py @@ -20,6 +20,8 @@ import os import inspect +from .. import utils +from ..utils import UtilError from .._exceptions import PluginError from .pluginorigin import PluginOrigin, PluginOriginType @@ -250,6 +252,8 @@ class PluginFactory: ) from e self._assert_plugin(kind, plugin_type) + self._assert_min_version(kind, plugin_type) + return (plugin_type, defaults) def _assert_plugin(self, kind, plugin_type): @@ -273,3 +277,44 @@ class PluginFactory: ), reason="setup-returns-not-type", ) from e + + def _assert_min_version(self, kind, plugin_type): + + 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 ?", + ) + + 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 + + bst_major, bst_minor = utils._get_bst_api_version() + + if min_version_major != bst_major: + raise PluginError( + "{} 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.", + ) + + 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 + ), + reason="incompatible-minor-version", + detail="Please upgrade to BuildStream {}".format(plugin_type.BST_MIN_VERSION), + ) diff --git a/src/buildstream/plugin.py b/src/buildstream/plugin.py index 4f2d74304..935db6523 100644 --- a/src/buildstream/plugin.py +++ b/src/buildstream/plugin.py @@ -148,6 +148,32 @@ class Plugin: which are included in the buildstream namespace. """ + BST_MIN_VERSION = None + """The minimum required version of BuildStream required by this plugin. + + 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. + + **Example:** + + 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:: + + 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 """True if this element plugin has been deprecated. 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) |