plugin.py: Add API to allow plugins to raise deprecation warnings
A plugin's deprecation warning may be silenced by a project by adding
the plugin to the list 'supress-deprecation-warnings' in the project's
project.conf
diff --git a/buildstream/_versions.py b/buildstream/_versions.py
index a9eb86d..5affc78 100644
--- a/buildstream/_versions.py
+++ b/buildstream/_versions.py
@@ -23,7 +23,7 @@
# This version is bumped whenever enhancements are made
# to the `project.conf` format or the core element format.
#
-BST_FORMAT_VERSION = 21
+BST_FORMAT_VERSION = 22
# The base BuildStream artifact version
diff --git a/buildstream/plugin.py b/buildstream/plugin.py
index 2f51c88..c21ae93 100644
--- a/buildstream/plugin.py
+++ b/buildstream/plugin.py
@@ -164,6 +164,25 @@
core format version :ref:`core format version <project_format_version>`.
"""
+ 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>`.
+
+ """
+
+ 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.
+
+ """
+
def __init__(self, name, context, project, provenance, type_tag):
self.name = name
@@ -188,6 +207,12 @@
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.
@@ -767,6 +792,20 @@
else:
return self.name
+ def __deprecation_warning_silenced(self):
+ if not self.BST_PLUGIN_DEPRECATED:
+ return False
+ else:
+ silenced_warnings = set()
+ project = self.__project
+ plugin_overrides = {**project.element_overrides, **project.source_overrides}
+
+ for key, value in self.node_items(plugin_overrides):
+ if value.get('suppress-deprecation-warnings', False):
+ silenced_warnings.add(key)
+
+ return self.get_kind() in silenced_warnings
+
# Hold on to a lookup table by counter of all instantiated plugins.
# We use this to send the id back from child processes so we can lookup
diff --git a/tests/plugins/deprecationwarnings/deprecationwarnings.py b/tests/plugins/deprecationwarnings/deprecationwarnings.py
new file mode 100644
index 0000000..799f162
--- /dev/null
+++ b/tests/plugins/deprecationwarnings/deprecationwarnings.py
@@ -0,0 +1,41 @@
+import pytest
+import tempfile
+import os
+from buildstream.plugintestutils import cli
+from buildstream import _yaml
+import buildstream.plugins.elements.manual
+
+
+DATA_DIR = os.path.join(
+ os.path.dirname(os.path.realpath(__file__)),
+ "project"
+)
+
+_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 = os.path.join(datafiles.dirname, datafiles.basename)
+ 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 = os.path.join(datafiles.dirname, datafiles.basename)
+ result = 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/project/elements/deprecated.bst b/tests/plugins/deprecationwarnings/project/elements/deprecated.bst
new file mode 100644
index 0000000..e80bd91
--- /dev/null
+++ b/tests/plugins/deprecationwarnings/project/elements/deprecated.bst
@@ -0,0 +1 @@
+kind: deprecated_plugin
\ No newline at end of file
diff --git a/tests/plugins/deprecationwarnings/project/plugins/elements/deprecated_plugin.py b/tests/plugins/deprecationwarnings/project/plugins/elements/deprecated_plugin.py
new file mode 100644
index 0000000..a8e3956
--- /dev/null
+++ b/tests/plugins/deprecationwarnings/project/plugins/elements/deprecated_plugin.py
@@ -0,0 +1,11 @@
+from buildstream import BuildElement, SandboxFlags
+
+
+class DeprecatedPlugin(BuildElement):
+ 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/project/plugins/elements/deprecated_plugin.yaml b/tests/plugins/deprecationwarnings/project/plugins/elements/deprecated_plugin.yaml
new file mode 100644
index 0000000..1c07cd8
--- /dev/null
+++ b/tests/plugins/deprecationwarnings/project/plugins/elements/deprecated_plugin.yaml
@@ -0,0 +1,22 @@
+# 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/project.conf b/tests/plugins/deprecationwarnings/project/project.conf
new file mode 100644
index 0000000..18e368f
--- /dev/null
+++ b/tests/plugins/deprecationwarnings/project/project.conf
@@ -0,0 +1,15 @@
+# Unique project name
+name: deprecation-warnings
+
+# Required BuildStream format version
+format-version: 20
+
+# Subdirectory where elements are stored
+element-path: elements
+
+plugins:
+
+- origin: local
+ path: plugins/elements
+ elements:
+ deprecated_plugin: 0