summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Van Berkom <tristan.vanberkom@codethink.co.uk>2020-04-30 16:21:19 +0900
committerTristan Van Berkom <tristan.vanberkom@codethink.co.uk>2020-05-03 13:30:13 +0900
commit2f31c8ae5fc3f7cbd0bf582f6637dca00d5e7842 (patch)
tree10a02cd17a425651d3e0381dd8888f9aa68644e8
parente13275bdd92aae182d7e93f5b916c4fc4fd280f8 (diff)
downloadbuildstream-tristan/deprecation-warnings-refactor.tar.gz
plugin.py: Rework how deprecation warnings are configured.tristan/deprecation-warnings-refactor
This is mostly a semantic change which defines how deprecation warnings are suppressed in a more consistent fashion, by declaring such suppressions in the plugin origin declarations rather than on the generic element/source configuration overrides section. Other side effects of this commit are that the warnings have been enhanced to include the provenance of whence the deprecated plugins have been used in the project, and that the custom deprecation message is optional and will appear in the message detail string rather than in the primary warning text, which now simply indicates that the plugin being used is deprecated. Documentation and test cases are updated. This fixes #1291
-rw-r--r--NEWS8
-rw-r--r--doc/source/format_project.rst57
-rw-r--r--src/buildstream/_pluginfactory/elementfactory.py2
-rw-r--r--src/buildstream/_pluginfactory/pluginfactory.py37
-rw-r--r--src/buildstream/_pluginfactory/pluginorigin.py65
-rw-r--r--src/buildstream/_pluginfactory/sourcefactory.py2
-rw-r--r--src/buildstream/_project.py8
-rw-r--r--src/buildstream/_scheduler/jobs/jobpickler.py2
-rw-r--r--src/buildstream/plugin.py39
-rw-r--r--tests/plugins/deprecationwarnings.py38
-rw-r--r--tests/plugins/deprecationwarnings/elements/deprecated.bst1
-rw-r--r--tests/plugins/deprecationwarnings/plugins/elements/deprecated_plugin.py12
-rw-r--r--tests/plugins/deprecationwarnings/plugins/elements/deprecated_plugin.yaml22
-rw-r--r--tests/plugins/deprecationwarnings/project.conf15
-rw-r--r--tests/plugins/loading.py73
-rw-r--r--tests/plugins/loading/plugins/elements/deprecated/deprecated.py21
-rw-r--r--tests/plugins/loading/plugins/sources/deprecated/deprecated.py34
17 files changed, 296 insertions, 140 deletions
diff --git a/NEWS b/NEWS
index ec6f5f352..0b6882dc8 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,14 @@ CLI
o `bst shell --build` will now automatically fetch missing sources.
+Format
+------
+
+ o BREAKING CHANGE: Now deprecation warnings are suppressed using the `allow-deprecated`
+ configuration with the plugin origins in project.conf, instead of on the
+ source/element overrides section (See issue #1291)
+
+
==================
buildstream 1.93.3
==================
diff --git a/doc/source/format_project.rst b/doc/source/format_project.rst
index 65ca6c14d..211fc4dd0 100644
--- a/doc/source/format_project.rst
+++ b/doc/source/format_project.rst
@@ -404,7 +404,7 @@ plugin.
# We want to use the `mysource` source plugin located in our
# project's `plugins/sources` subdirectory.
sources:
- mysource: 0
+ - mysource
Pip plugins
@@ -425,11 +425,60 @@ system.
#
package-name: potato
- # We again must specify a minimal format version for the
- # external plugin, it is allowed to be `0`.
+ # We again must specify specifically which plugins we
+ # want loaded from this origin.
#
elements:
- starch: 0
+ - starch
+
+
+.. _project_plugins_deprecation:
+
+Suppressing deprecation warnings
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Plugins can be deprecated over time, and using deprecated plugins will
+trigger a warning when loading elements and sources which use
+deprecated plugin kinds.
+
+These deprecation warnings can be suppressed for the entire plugin
+origin or on a per plugin kind basis.
+
+To suppress all deprecation warnings from the origin, set the
+``allow-deprecated`` flag for the origin as follows:
+
+.. code:: yaml
+
+ plugins:
+
+ - origin: local
+ path: plugins/sources
+
+ # Suppress deprecation warnings for any plugins loaded here
+ allow-deprecated: True
+
+ sources:
+ - mysource
+
+
+In order to suppress deprecation warnings for a single element or
+source kind within an origin, you will have to use a dictionary
+to declare the specific plugin kind and set the ``allow-deprecated`` flag
+on that dictionary as follows:
+
+.. code:: yaml
+
+ plugins:
+
+ - origin: pip
+ package-name: potato
+
+ # Here we use a dictionary to declare the "starch"
+ # element kind, and specify that it is allowed to
+ # be deprecated.
+ #
+ elements:
+ - kind: starch
+ allow-deprecated: True
.. _project_options:
diff --git a/src/buildstream/_pluginfactory/elementfactory.py b/src/buildstream/_pluginfactory/elementfactory.py
index f66e3d436..da6e8ac56 100644
--- a/src/buildstream/_pluginfactory/elementfactory.py
+++ b/src/buildstream/_pluginfactory/elementfactory.py
@@ -53,6 +53,6 @@ class ElementFactory(PluginFactory):
# LoadError (if the element itself took issue with the config)
#
def create(self, context, project, meta):
- element_type, default_config = self.lookup(meta.kind, meta.provenance)
+ element_type, default_config = self.lookup(context.messenger, meta.kind, meta.provenance)
element = element_type(context, project, meta, default_config)
return element
diff --git a/src/buildstream/_pluginfactory/pluginfactory.py b/src/buildstream/_pluginfactory/pluginfactory.py
index c3bba5e31..d8a346efd 100644
--- a/src/buildstream/_pluginfactory/pluginfactory.py
+++ b/src/buildstream/_pluginfactory/pluginfactory.py
@@ -26,6 +26,8 @@ from ..plugin import Plugin
from ..node import ProvenanceInformation
from ..utils import UtilError
from .._exceptions import PluginError
+from .._messenger import Messenger
+from .._message import Message, MessageType
from .pluginorigin import PluginOrigin, PluginOriginType
@@ -64,6 +66,7 @@ class PluginFactory:
self._base_type = base_type # The base class plugins derive from
self._types = {} # Plugin type lookup table by kind
self._origins = {} # PluginOrigin lookup table by kind
+ self._allow_deprecated = {} # Lookup table to check if a plugin is allowed to be deprecated
# The PluginSource object
self._plugin_base = plugin_base
@@ -118,6 +121,7 @@ class PluginFactory:
# Fetches a type loaded from a plugin in this plugin context
#
# Args:
+ # messenger (Messenger): The messenger
# kind (str): The kind of Plugin to create
# provenance (ProvenanceInformation): The provenance from where
# the plugin was referenced
@@ -128,8 +132,31 @@ class PluginFactory:
#
# Raises: PluginError
#
- def lookup(self, kind: str, provenance: ProvenanceInformation) -> Tuple[Type[Plugin], str]:
- return self._ensure_plugin(kind, provenance)
+ def lookup(self, messenger: Messenger, kind: str, provenance: ProvenanceInformation) -> Tuple[Type[Plugin], str]:
+ plugin_type, defaults = self._ensure_plugin(kind, provenance)
+
+ # We can be called with None for the messenger here in the
+ # case that we've been pickled through the scheduler (see jobpickler.py),
+ #
+ # In this case we know that we've already initialized and do not need
+ # to warn about deprecated plugins a second time.
+ if messenger is None:
+ return (plugin_type, defaults)
+
+ # After looking up the type, issue a warning if it's deprecated
+ #
+ # We do this here because we want to issue one warning for each time the
+ # plugin is used.
+ #
+ if plugin_type.BST_PLUGIN_DEPRECATED and not self._allow_deprecated[kind]:
+ message = Message(
+ MessageType.WARN,
+ "{}: Using deprecated plugin '{}'".format(provenance, kind),
+ detail=plugin_type.BST_PLUGIN_DEPRECATION_MESSAGE,
+ )
+ messenger.message(message)
+
+ return (plugin_type, defaults)
# register_plugin_origin():
#
@@ -138,8 +165,9 @@ class PluginFactory:
# Args:
# kind (str): The kind identifier of the Plugin
# origin (PluginOrigin): The PluginOrigin providing the plugin
+ # allow_deprecated (bool): Whether this plugin kind is allowed to be used in a deprecated state
#
- def register_plugin_origin(self, kind: str, origin: PluginOrigin):
+ def register_plugin_origin(self, kind: str, origin: PluginOrigin, allow_deprecated: bool):
if kind in self._origins:
raise PluginError(
"More than one {} plugin registered as kind '{}'".format(self._base_type.__name__, kind),
@@ -147,6 +175,7 @@ class PluginFactory:
)
self._origins[kind] = origin
+ self._allow_deprecated[kind] = allow_deprecated
# all_loaded_plugins():
#
@@ -224,7 +253,7 @@ class PluginFactory:
if kind not in self._site_source.list_plugins():
raise PluginError(
"{}: No {} type registered for kind '{}'".format(provenance, self._base_type.__name__, kind),
- reason="plugin-not-found"
+ reason="plugin-not-found",
)
source = self._site_source
diff --git a/src/buildstream/_pluginfactory/pluginorigin.py b/src/buildstream/_pluginfactory/pluginorigin.py
index 50852711b..14d7a76bf 100644
--- a/src/buildstream/_pluginfactory/pluginorigin.py
+++ b/src/buildstream/_pluginfactory/pluginorigin.py
@@ -18,6 +18,9 @@
import os
from ..types import FastEnum
+from ..node import ScalarNode, MappingNode
+from .._exceptions import LoadError
+from ..exceptions import LoadErrorReason
# PluginOriginType:
@@ -29,6 +32,17 @@ class PluginOriginType(FastEnum):
PIP = "pip"
+# PluginConfiguration:
+#
+# An object representing the configuration of a single
+# plugin in the origin.
+#
+class PluginConfiguration:
+ def __init__(self, kind, allow_deprecated):
+ self.kind = kind
+ self.allow_deprecated = allow_deprecated
+
+
# PluginOrigin
#
# Base class holding common properties of all origins.
@@ -36,18 +50,19 @@ class PluginOriginType(FastEnum):
class PluginOrigin:
# Common fields valid for all plugin origins
- _COMMON_CONFIG_KEYS = ["origin", "sources", "elements"]
+ _COMMON_CONFIG_KEYS = ["origin", "sources", "elements", "allow-deprecated"]
def __init__(self, origin_type):
# Public
- self.origin_type = origin_type
- self.elements = []
- self.sources = []
+ self.origin_type = origin_type # The PluginOriginType
+ self.elements = {} # A dictionary of PluginConfiguration
+ self.sources = {} # A dictionary of PluginConfiguration objects
# Private
self._project = None
self._kinds = {}
+ self._allow_deprecated = False
# new_from_node()
#
@@ -73,8 +88,14 @@ class PluginOrigin:
origin._project = project
origin._load(origin_node)
- origin.elements = origin_node.get_str_list("elements", [])
- origin.sources = origin_node.get_str_list("sources", [])
+ # Parse commonly defined aspects of PluginOrigins
+ origin._allow_deprecated = origin_node.get_bool("allow-deprecated", False)
+
+ element_sequence = origin_node.get_sequence("elements", [])
+ origin._load_plugin_configurations(element_sequence, origin.elements)
+
+ source_sequence = origin_node.get_sequence("sources", [])
+ origin._load_plugin_configurations(source_sequence, origin.sources)
return origin
@@ -89,6 +110,38 @@ class PluginOrigin:
def _load(self, origin_node):
pass
+ # _load_plugin_configurations()
+ #
+ # Helper function to load the list of source or element
+ # PluginConfigurations
+ #
+ # Args:
+ # sequence_node (SequenceNode): The list of configurations
+ # dictionary (dict): The location to store the results
+ #
+ def _load_plugin_configurations(self, sequence_node, dictionary):
+
+ for node in sequence_node:
+
+ # Parse as a simple string
+ if type(node) is ScalarNode: # pylint: disable=unidiomatic-typecheck
+ kind = node.as_str()
+ conf = PluginConfiguration(kind, self._allow_deprecated)
+
+ # Parse as a dictionary
+ elif type(node) is MappingNode: # pylint: disable=unidiomatic-typecheck
+ node.validate_keys(["kind", "allow-deprecated"])
+ kind = node.get_str("kind")
+ allow_deprecated = node.get_bool("allow-deprecated", self._allow_deprecated)
+ conf = PluginConfiguration(kind, allow_deprecated)
+ else:
+ p = node.get_provenance()
+ raise LoadError(
+ "{}: Plugin is not specified as a string or a dictionary".format(p), LoadErrorReason.INVALID_DATA
+ )
+
+ dictionary[kind] = conf
+
# PluginOriginLocal
#
diff --git a/src/buildstream/_pluginfactory/sourcefactory.py b/src/buildstream/_pluginfactory/sourcefactory.py
index fb219aa5e..5277577d4 100644
--- a/src/buildstream/_pluginfactory/sourcefactory.py
+++ b/src/buildstream/_pluginfactory/sourcefactory.py
@@ -54,6 +54,6 @@ class SourceFactory(PluginFactory):
# LoadError (if the source itself took issue with the config)
#
def create(self, context, project, meta):
- source_type, _ = self.lookup(meta.kind, meta.provenance)
+ source_type, _ = self.lookup(context.messenger, meta.kind, meta.provenance)
source = source_type(context, project, meta)
return source
diff --git a/src/buildstream/_project.py b/src/buildstream/_project.py
index 40524d7ad..45f3b4d34 100644
--- a/src/buildstream/_project.py
+++ b/src/buildstream/_project.py
@@ -951,10 +951,10 @@ class Project:
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)
+ for kind, conf in origin.elements.items():
+ output.element_factory.register_plugin_origin(kind, origin, conf.allow_deprecated)
+ for kind, conf in origin.sources.items():
+ output.source_factory.register_plugin_origin(kind, origin, conf.allow_deprecated)
# _warning_is_fatal():
#
diff --git a/src/buildstream/_scheduler/jobs/jobpickler.py b/src/buildstream/_scheduler/jobs/jobpickler.py
index 48e61cf5d..066e518c8 100644
--- a/src/buildstream/_scheduler/jobs/jobpickler.py
+++ b/src/buildstream/_scheduler/jobs/jobpickler.py
@@ -192,7 +192,7 @@ def _reduce_plugin_with_factory_dict(plugin, plugin_class_to_factory):
def _new_plugin_from_reduction_args(factory, meta_kind):
- cls, _ = factory.lookup(meta_kind, None)
+ cls, _ = factory.lookup(None, meta_kind, None)
plugin = cls.__new__(cls)
# Note that we rely on the `__project` member of the Plugin to keep
diff --git a/src/buildstream/plugin.py b/src/buildstream/plugin.py
index 935db6523..61d4c7153 100644
--- a/src/buildstream/plugin.py
+++ b/src/buildstream/plugin.py
@@ -177,20 +177,18 @@ class Plugin:
BST_PLUGIN_DEPRECATED = False
"""True if this element plugin has been deprecated.
- If this is set to true, BuildStream will emmit a deprecation
- warning when this plugin is loaded. This deprecation warning may
- be suppressed on a plugin by plugin basis by setting
- ``suppress-deprecation-warnings: true`` in the relevent section of
- the project's :ref:`plugin configuration overrides <project_overrides>`.
+ If this is set to true, BuildStream will emmit a deprecation warning
+ in any place where this plugin is used.
+ The deprecation warnings can be suppressed when defining the
+ :ref:`plugin origins in your project configuration <project_plugins_deprecation>`
"""
- BST_PLUGIN_DEPRECATION_MESSAGE = ""
- """ The message printed when this element shows a deprecation warning.
-
- This should be set if BST_PLUGIN_DEPRECATED is True and should direct the user
- to the deprecated plug-in's replacement.
+ BST_PLUGIN_DEPRECATION_MESSAGE = None
+ """An additional message to report when a plugin is deprecated
+ This can be used to refer the user to a suitable replacement or
+ alternative approach when the plugin is deprecated.
"""
# Unique id generator for Plugins
@@ -272,11 +270,6 @@ class Plugin:
self.__kind = modulename.split(".")[-1]
self.debug("Created: {}".format(self))
- # If this plugin has been deprecated, emit a warning.
- if self.BST_PLUGIN_DEPRECATED and not self.__deprecation_warning_silenced():
- detail = "Using deprecated plugin {}: {}".format(self.__kind, self.BST_PLUGIN_DEPRECATION_MESSAGE)
- self.__message(MessageType.WARN, detail)
-
def __del__(self):
# Dont send anything through the Message() pipeline at destruction time,
# any subsequent lookup of plugin by unique id would raise KeyError.
@@ -762,22 +755,6 @@ class Plugin:
output.flush()
self.status("Running host command", detail=command)
- def __deprecation_warning_silenced(self):
- if not self.BST_PLUGIN_DEPRECATED:
- return False
- else:
- silenced_warnings = set()
- project = self.__project
-
- for key, value in project.element_overrides.items():
- if value.get_bool("suppress-deprecation-warnings", default=False):
- silenced_warnings.add(key)
- for key, value in project.source_overrides.items():
- if value.get_bool("suppress-deprecation-warnings", default=False):
- silenced_warnings.add(key)
-
- return self.get_kind() in silenced_warnings
-
def __get_full_name(self):
project = self.__project
# Set the name, depending on element or source plugin type
diff --git a/tests/plugins/deprecationwarnings.py b/tests/plugins/deprecationwarnings.py
deleted file mode 100644
index a4da3ea72..000000000
--- a/tests/plugins/deprecationwarnings.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# Pylint doesn't play well with fixtures and dependency injection from pytest
-# pylint: disable=redefined-outer-name
-
-import os
-
-import pytest
-
-from buildstream.testing import cli # pylint: disable=unused-import
-
-
-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)
-
-
-@pytest.mark.datafiles(DATA_DIR)
-def test_deprecation_warning_present(cli, datafiles):
- project = str(datafiles)
- result = cli.run(project=project, args=["show", "deprecated.bst"])
- result.assert_success()
- assert _DEPRECATION_WARNING in result.stderr
-
-
-@pytest.mark.datafiles(DATA_DIR)
-def test_suppress_deprecation_warning(cli, datafiles):
- project = str(datafiles)
- cli.run(project=project, args=["show", "manual.bst"])
-
- element_overrides = "elements:\n" " deprecated_plugin:\n" " suppress-deprecation-warnings : True\n"
-
- project_conf = os.path.join(project, "project.conf")
- with open(project_conf, "a") as f:
- f.write(element_overrides)
-
- result = cli.run(project=project, args=["show", "deprecated.bst"])
- result.assert_success()
- assert _DEPRECATION_WARNING not in result.stderr
diff --git a/tests/plugins/deprecationwarnings/elements/deprecated.bst b/tests/plugins/deprecationwarnings/elements/deprecated.bst
deleted file mode 100644
index e80bd91cd..000000000
--- a/tests/plugins/deprecationwarnings/elements/deprecated.bst
+++ /dev/null
@@ -1 +0,0 @@
-kind: deprecated_plugin \ No newline at end of file
diff --git a/tests/plugins/deprecationwarnings/plugins/elements/deprecated_plugin.py b/tests/plugins/deprecationwarnings/plugins/elements/deprecated_plugin.py
deleted file mode 100644
index 244009764..000000000
--- a/tests/plugins/deprecationwarnings/plugins/elements/deprecated_plugin.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from buildstream import BuildElement
-
-
-class DeprecatedPlugin(BuildElement):
- BST_MIN_VERSION = "2.0"
- BST_PLUGIN_DEPRECATED = True
- BST_PLUGIN_DEPRECATION_MESSAGE = "Here is some detail."
-
-
-# Plugin entry point
-def setup():
- return DeprecatedPlugin
diff --git a/tests/plugins/deprecationwarnings/plugins/elements/deprecated_plugin.yaml b/tests/plugins/deprecationwarnings/plugins/elements/deprecated_plugin.yaml
deleted file mode 100644
index 1c07cd8b2..000000000
--- a/tests/plugins/deprecationwarnings/plugins/elements/deprecated_plugin.yaml
+++ /dev/null
@@ -1,22 +0,0 @@
-# Deprecated-plugin build element does not provide any default
-# build commands
-config:
-
- # Commands for configuring the software
- #
- configure-commands: []
-
- # Commands for building the software
- #
- build-commands: []
-
- # Commands for installing the software into a
- # destination folder
- #
- install-commands: []
-
- # Commands for stripping installed binaries
- #
- strip-commands:
- - |
- %{strip-binaries} \ No newline at end of file
diff --git a/tests/plugins/deprecationwarnings/project.conf b/tests/plugins/deprecationwarnings/project.conf
deleted file mode 100644
index 9e03afe0a..000000000
--- a/tests/plugins/deprecationwarnings/project.conf
+++ /dev/null
@@ -1,15 +0,0 @@
-# Unique project name
-name: deprecation-warnings
-
-# Required BuildStream version
-min-version: 2.0
-
-# Subdirectory where elements are stored
-element-path: elements
-
-plugins:
-
-- origin: local
- path: plugins/elements
- elements:
- - deprecated_plugin
diff --git a/tests/plugins/loading.py b/tests/plugins/loading.py
index a54df776e..152f4080b 100644
--- a/tests/plugins/loading.py
+++ b/tests/plugins/loading.py
@@ -230,3 +230,76 @@ def test_plugin_found(cli, datafiles, plugin_type):
result = cli.run(project=project, args=["show", "element.bst"])
result.assert_success()
+
+
+@pytest.mark.datafiles(DATA_DIR)
+@pytest.mark.parametrize("plugin_type", [("elements"), ("sources")])
+def test_deprecation_warnings(cli, datafiles, plugin_type):
+ project = str(datafiles)
+
+ update_project(
+ project,
+ {
+ "plugins": [
+ {
+ "origin": "local",
+ "path": os.path.join("plugins", plugin_type, "deprecated"),
+ plugin_type: ["deprecated"],
+ }
+ ]
+ },
+ )
+ setup_element(project, plugin_type, "deprecated")
+
+ result = cli.run(project=project, args=["show", "element.bst"])
+ result.assert_success()
+ assert "Here is some detail." in result.stderr
+
+
+@pytest.mark.datafiles(DATA_DIR)
+@pytest.mark.parametrize("plugin_type", [("elements"), ("sources")])
+def test_deprecation_warning_suppressed_by_origin(cli, datafiles, plugin_type):
+ project = str(datafiles)
+
+ update_project(
+ project,
+ {
+ "plugins": [
+ {
+ "origin": "local",
+ "path": os.path.join("plugins", plugin_type, "deprecated"),
+ "allow-deprecated": True,
+ plugin_type: ["deprecated"],
+ }
+ ]
+ },
+ )
+ setup_element(project, plugin_type, "deprecated")
+
+ result = cli.run(project=project, args=["show", "element.bst"])
+ result.assert_success()
+ assert "Here is some detail." not in result.stderr
+
+
+@pytest.mark.datafiles(DATA_DIR)
+@pytest.mark.parametrize("plugin_type", [("elements"), ("sources")])
+def test_deprecation_warning_suppressed_specifically(cli, datafiles, plugin_type):
+ project = str(datafiles)
+
+ update_project(
+ project,
+ {
+ "plugins": [
+ {
+ "origin": "local",
+ "path": os.path.join("plugins", plugin_type, "deprecated"),
+ plugin_type: [{"kind": "deprecated", "allow-deprecated": True}],
+ }
+ ]
+ },
+ )
+ setup_element(project, plugin_type, "deprecated")
+
+ result = cli.run(project=project, args=["show", "element.bst"])
+ result.assert_success()
+ assert "Here is some detail." not in result.stderr
diff --git a/tests/plugins/loading/plugins/elements/deprecated/deprecated.py b/tests/plugins/loading/plugins/elements/deprecated/deprecated.py
new file mode 100644
index 000000000..7184710bc
--- /dev/null
+++ b/tests/plugins/loading/plugins/elements/deprecated/deprecated.py
@@ -0,0 +1,21 @@
+from buildstream import Element
+
+
+class Deprecated(Element):
+ BST_MIN_VERSION = "2.0"
+ BST_PLUGIN_DEPRECATED = True
+ BST_PLUGIN_DEPRECATION_MESSAGE = "Here is some detail."
+
+ def configure(self, node):
+ pass
+
+ def preflight(self):
+ pass
+
+ def get_unique_key(self):
+ return {}
+
+
+# Plugin entry point
+def setup():
+ return Deprecated
diff --git a/tests/plugins/loading/plugins/sources/deprecated/deprecated.py b/tests/plugins/loading/plugins/sources/deprecated/deprecated.py
new file mode 100644
index 000000000..6203eb2fa
--- /dev/null
+++ b/tests/plugins/loading/plugins/sources/deprecated/deprecated.py
@@ -0,0 +1,34 @@
+from buildstream import Source
+
+
+class Deprecated(Source):
+ BST_MIN_VERSION = "2.0"
+ BST_PLUGIN_DEPRECATED = True
+ BST_PLUGIN_DEPRECATION_MESSAGE = "Here is some detail."
+
+ def configure(self, node):
+ pass
+
+ def preflight(self):
+ pass
+
+ def get_unique_key(self):
+ return {}
+
+ def load_ref(self, node):
+ pass
+
+ def get_ref(self):
+ return {}
+
+ def set_ref(self, ref, node):
+ pass
+
+ def is_cached(self):
+ return False
+
+
+# Plugin entry point
+def setup():
+
+ return Deprecated