summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorValentin David <valentin.david@codethink.co.uk>2018-07-18 11:37:31 +0200
committerValentin David <valentin.david@codethink.co.uk>2018-08-02 16:17:01 +0200
commit19cd954bf9e22cbd6b7adacc9d87a693811830dc (patch)
tree07eec4174828f3e15821298e920ae91045f0c4c1
parent483b0223bccad8c4c843d445f6621eefe2000744 (diff)
downloadbuildstream-19cd954bf9e22cbd6b7adacc9d87a693811830dc.tar.gz
Refactor plugin factory creation
-rw-r--r--buildstream/_elementfactory.py13
-rw-r--r--buildstream/_plugincontext.py18
-rw-r--r--buildstream/_project.py124
-rw-r--r--buildstream/_sourcefactory.py13
-rw-r--r--tests/plugins/basics.py32
-rw-r--r--tests/plugins/third_party.py6
6 files changed, 115 insertions, 91 deletions
diff --git a/buildstream/_elementfactory.py b/buildstream/_elementfactory.py
index 9d5b258cb..00847e66f 100644
--- a/buildstream/_elementfactory.py
+++ b/buildstream/_elementfactory.py
@@ -31,9 +31,13 @@ from .element import Element
#
class ElementFactory(PluginContext):
- def __init__(self, plugin_base, plugin_origins=None):
+ def __init__(self, plugin_base, *,
+ format_versions={},
+ plugin_origins=None):
- super().__init__(plugin_base, Element, [_site.element_plugins], plugin_origins)
+ super().__init__(plugin_base, Element, [_site.element_plugins],
+ plugin_origins=plugin_origins,
+ format_versions=format_versions)
# create():
#
@@ -54,4 +58,7 @@ class ElementFactory(PluginContext):
#
def create(self, context, project, artifacts, meta):
element_type, default_config = self.lookup(meta.kind)
- return element_type(context, project, artifacts, meta, default_config)
+ element = element_type(context, project, artifacts, meta, default_config)
+ version = self._format_versions.get(meta.kind, 0)
+ self._assert_plugin_format(element, version)
+ return element
diff --git a/buildstream/_plugincontext.py b/buildstream/_plugincontext.py
index 38d2231ba..5a7097485 100644
--- a/buildstream/_plugincontext.py
+++ b/buildstream/_plugincontext.py
@@ -20,7 +20,7 @@
import os
import inspect
-from ._exceptions import PluginError
+from ._exceptions import PluginError, LoadError, LoadErrorReason
from . import utils
@@ -41,7 +41,9 @@ from . import utils
#
class PluginContext():
- def __init__(self, plugin_base, base_type, site_plugin_path, plugin_origins=None, dependencies=None):
+ def __init__(self, plugin_base, base_type, site_plugin_path, *,
+ plugin_origins=None, dependencies=None,
+ format_versions={}):
# The plugin kinds which were loaded
self.loaded_dependencies = []
@@ -58,6 +60,7 @@ class PluginContext():
self._plugin_base = plugin_base
self._site_source = plugin_base.make_plugin_source(searchpath=site_plugin_path)
self._alternate_sources = {}
+ self._format_versions = format_versions
# lookup():
#
@@ -219,3 +222,14 @@ class PluginContext():
self._base_type.__name__, kind,
plugin_type.BST_REQUIRED_VERSION_MAJOR,
plugin_type.BST_REQUIRED_VERSION_MINOR))
+
+ # _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(LoadErrorReason.UNSUPPORTED_PLUGIN,
+ "{}: Format version {} is too old for requested version {}"
+ .format(plugin, plugin.BST_FORMAT_VERSION, version))
diff --git a/buildstream/_project.py b/buildstream/_project.py
index 12f23e2e4..faecec87f 100644
--- a/buildstream/_project.py
+++ b/buildstream/_project.py
@@ -104,18 +104,17 @@ class Project():
#
self._context = context # The invocation Context
self._aliases = {} # Aliases dictionary
- self._plugin_source_origins = [] # Origins of custom sources
- self._plugin_element_origins = [] # Origins of custom elements
self._cli_options = cli_options
self._cache_key = None
- self._source_format_versions = {}
- self._element_format_versions = {}
self._shell_command = [] # The default interactive shell command
self._shell_environment = {} # Statically set environment vars
self._shell_host_files = [] # A list of HostMount objects
+ self._element_factory = None
+ self._source_factory = None
+
profile_start(Topics.LOAD_PROJECT, self.directory.replace(os.sep, '-'))
self._load()
profile_end(Topics.LOAD_PROJECT, self.directory.replace(os.sep, '-'))
@@ -189,10 +188,7 @@ class Project():
# (Element): A newly created Element object of the appropriate kind
#
def create_element(self, artifacts, meta):
- element = self._element_factory.create(self._context, self, artifacts, meta)
- version = self._element_format_versions.get(meta.kind, 0)
- self._assert_plugin_format(element, version)
- return element
+ return self._element_factory.create(self._context, self, artifacts, meta)
# create_source()
#
@@ -205,10 +201,7 @@ class Project():
# (Source): A newly created Source object of the appropriate kind
#
def create_source(self, meta):
- source = self._source_factory.create(self._context, self, meta)
- version = self._source_format_versions.get(meta.kind, 0)
- self._assert_plugin_format(source, version)
- return source
+ return self._source_factory.create(self._context, self, meta)
# get_alias_uri()
#
@@ -394,49 +387,7 @@ class Project():
# Load artifacts pull/push configuration for this project
self.artifact_cache_specs = ArtifactCache.specs_from_config_node(config, self.directory)
- # Plugin origins and versions
- origins = _yaml.node_get(config, list, 'plugins', default_value=[])
- for origin in origins:
- allowed_origin_fields = [
- 'origin', 'sources', 'elements',
- 'package-name', 'path',
- ]
- allowed_origins = ['core', 'local', 'pip']
- _yaml.node_validate(origin, allowed_origin_fields)
-
- if origin['origin'] not in allowed_origins:
- raise LoadError(
- LoadErrorReason.INVALID_YAML,
- "Origin '{}' is not one of the allowed types"
- .format(origin['origin']))
-
- # Store source versions for checking later
- source_versions = _yaml.node_get(origin, Mapping, 'sources', default_value={})
- for key, _ in _yaml.node_items(source_versions):
- if key in self._source_format_versions:
- raise LoadError(
- LoadErrorReason.INVALID_YAML,
- "Duplicate listing of source '{}'".format(key))
- self._source_format_versions[key] = _yaml.node_get(source_versions, int, key)
-
- # Store element versions for checking later
- element_versions = _yaml.node_get(origin, Mapping, 'elements', default_value={})
- for key, _ in _yaml.node_items(element_versions):
- if key in self._element_format_versions:
- raise LoadError(
- LoadErrorReason.INVALID_YAML,
- "Duplicate listing of element '{}'".format(key))
- self._element_format_versions[key] = _yaml.node_get(element_versions, int, key)
-
- # Store the origins if they're not 'core'.
- # core elements are loaded by default, so storing is unnecessary.
- if _yaml.node_get(origin, str, 'origin') != 'core':
- self._store_origin(origin, 'sources', self._plugin_source_origins)
- self._store_origin(origin, 'elements', self._plugin_element_origins)
-
- pluginbase = PluginBase(package='buildstream.plugins')
- self._element_factory = ElementFactory(pluginbase, self._plugin_element_origins)
- self._source_factory = SourceFactory(pluginbase, self._plugin_source_origins)
+ self._load_plugin_factories(config)
# Source url aliases
self._aliases = _yaml.node_get(config, Mapping, 'aliases', default_value={})
@@ -525,16 +476,59 @@ class Project():
if not self.default_mirror:
self.default_mirror = mirror_name
- # _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(LoadErrorReason.UNSUPPORTED_PLUGIN,
- "{}: Format version {} is too old for requested version {}"
- .format(plugin, plugin.BST_FORMAT_VERSION, version))
+ def _load_plugin_factories(self, config):
+ plugin_source_origins = [] # Origins of custom sources
+ plugin_element_origins = [] # Origins of custom elements
+
+ # Plugin origins and versions
+ origins = _yaml.node_get(config, list, 'plugins', default_value=[])
+ source_format_versions = {}
+ element_format_versions = {}
+ for origin in origins:
+ allowed_origin_fields = [
+ 'origin', 'sources', 'elements',
+ 'package-name', 'path',
+ ]
+ allowed_origins = ['core', 'local', 'pip']
+ _yaml.node_validate(origin, allowed_origin_fields)
+
+ if origin['origin'] not in allowed_origins:
+ raise LoadError(
+ LoadErrorReason.INVALID_YAML,
+ "Origin '{}' is not one of the allowed types"
+ .format(origin['origin']))
+
+ # Store source versions for checking later
+ source_versions = _yaml.node_get(origin, Mapping, 'sources', default_value={})
+ for key, _ in _yaml.node_items(source_versions):
+ if key in source_format_versions:
+ raise LoadError(
+ LoadErrorReason.INVALID_YAML,
+ "Duplicate listing of source '{}'".format(key))
+ source_format_versions[key] = _yaml.node_get(source_versions, int, key)
+
+ # Store element versions for checking later
+ element_versions = _yaml.node_get(origin, Mapping, 'elements', default_value={})
+ for key, _ in _yaml.node_items(element_versions):
+ if key in element_format_versions:
+ raise LoadError(
+ LoadErrorReason.INVALID_YAML,
+ "Duplicate listing of element '{}'".format(key))
+ element_format_versions[key] = _yaml.node_get(element_versions, int, key)
+
+ # Store the origins if they're not 'core'.
+ # core elements are loaded by default, so storing is unnecessary.
+ if _yaml.node_get(origin, str, 'origin') != 'core':
+ self._store_origin(origin, 'sources', plugin_source_origins)
+ self._store_origin(origin, 'elements', plugin_element_origins)
+
+ pluginbase = PluginBase(package='buildstream.plugins')
+ self._element_factory = ElementFactory(pluginbase,
+ plugin_origins=plugin_element_origins,
+ format_versions=element_format_versions)
+ self._source_factory = SourceFactory(pluginbase,
+ plugin_origins=plugin_source_origins,
+ format_versions=source_format_versions)
# _store_origin()
#
diff --git a/buildstream/_sourcefactory.py b/buildstream/_sourcefactory.py
index 88a130e10..1d959a140 100644
--- a/buildstream/_sourcefactory.py
+++ b/buildstream/_sourcefactory.py
@@ -31,9 +31,13 @@ from .source import Source
#
class SourceFactory(PluginContext):
- def __init__(self, plugin_base, plugin_origins=None):
+ def __init__(self, plugin_base, *,
+ format_versions={},
+ plugin_origins=None):
- super().__init__(plugin_base, Source, [_site.source_plugins], plugin_origins)
+ super().__init__(plugin_base, Source, [_site.source_plugins],
+ format_versions=format_versions,
+ plugin_origins=plugin_origins)
# create():
#
@@ -54,4 +58,7 @@ class SourceFactory(PluginContext):
#
def create(self, context, project, meta):
source_type, _ = self.lookup(meta.kind)
- return source_type(context, project, meta)
+ 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/tests/plugins/basics.py b/tests/plugins/basics.py
index 740a20c66..4c9cbafe4 100644
--- a/tests/plugins/basics.py
+++ b/tests/plugins/basics.py
@@ -49,7 +49,7 @@ def test_custom_source(plugin_fixture, datafiles):
datafiles.basename),
'plugins': {'foo': 0}
}]
- factory = SourceFactory(plugin_fixture['base'], plugins)
+ factory = SourceFactory(plugin_fixture['base'], plugin_origins=plugins)
assert(isinstance(factory, SourceFactory))
foo_type, _ = factory.lookup('foo')
@@ -64,7 +64,7 @@ def test_custom_element(plugin_fixture, datafiles):
datafiles.basename),
'plugins': {'foo': 0}
}]
- factory = ElementFactory(plugin_fixture['base'], plugins)
+ factory = ElementFactory(plugin_fixture['base'], plugin_origins=plugins)
assert(isinstance(factory, ElementFactory))
foo_type, _ = factory.lookup('foo')
@@ -101,7 +101,7 @@ def test_source_notatype(plugin_fixture, datafiles):
datafiles.basename),
'plugins': {'foo': 0}
}]
- factory = SourceFactory(plugin_fixture['base'], plugins)
+ factory = SourceFactory(plugin_fixture['base'], plugin_origins=plugins)
with pytest.raises(PluginError) as exc:
foo_type = factory.lookup('foo')
@@ -115,7 +115,7 @@ def test_element_notatype(plugin_fixture, datafiles):
datafiles.basename),
'plugins': {'foo': 0}
}]
- factory = ElementFactory(plugin_fixture['base'], plugins)
+ factory = ElementFactory(plugin_fixture['base'], plugin_origins=plugins)
with pytest.raises(PluginError) as exc:
foo_type = factory.lookup('foo')
@@ -130,7 +130,7 @@ def test_source_wrongtype(plugin_fixture, datafiles):
datafiles.basename),
'plugins': {'foo': 0}
}]
- factory = SourceFactory(plugin_fixture['base'], plugins)
+ factory = SourceFactory(plugin_fixture['base'], plugin_origins=plugins)
with pytest.raises(PluginError) as exc:
foo_type = factory.lookup('foo')
@@ -145,7 +145,7 @@ def test_element_wrongtype(plugin_fixture, datafiles):
datafiles.basename),
'plugins': {'foo': 0}
}]
- factory = ElementFactory(plugin_fixture['base'], plugins)
+ factory = ElementFactory(plugin_fixture['base'], plugin_origins=plugins)
with pytest.raises(PluginError) as exc:
foo_type = factory.lookup('foo')
@@ -159,7 +159,7 @@ def test_source_missing_setup(plugin_fixture, datafiles):
datafiles.basename),
'plugins': {'foo': 0}
}]
- factory = SourceFactory(plugin_fixture['base'], plugins)
+ factory = SourceFactory(plugin_fixture['base'], plugin_origins=plugins)
with pytest.raises(PluginError) as exc:
foo_type = factory.lookup('foo')
@@ -173,7 +173,7 @@ def test_element_missing_setup(plugin_fixture, datafiles):
datafiles.basename),
'plugins': {'foo': 0}
}]
- factory = ElementFactory(plugin_fixture['base'], plugins)
+ factory = ElementFactory(plugin_fixture['base'], plugin_origins=plugins)
with pytest.raises(PluginError) as exc:
foo_type = factory.lookup('foo')
@@ -188,7 +188,7 @@ def test_source_bad_setup(plugin_fixture, datafiles):
datafiles.basename),
'plugins': {'foo': 0}
}]
- factory = SourceFactory(plugin_fixture['base'], plugins)
+ factory = SourceFactory(plugin_fixture['base'], plugin_origins=plugins)
with pytest.raises(PluginError) as exc:
foo_type = factory.lookup('foo')
@@ -203,7 +203,7 @@ def test_element_bad_setup(plugin_fixture, datafiles):
datafiles.basename),
'plugins': {'foo': 0}
}]
- factory = ElementFactory(plugin_fixture['base'], plugins)
+ factory = ElementFactory(plugin_fixture['base'], plugin_origins=plugins)
with pytest.raises(PluginError) as exc:
foo_type = factory.lookup('foo')
@@ -218,7 +218,7 @@ def test_source_badversion(plugin_fixture, datafiles):
datafiles.basename),
'plugins': {'foo': 0}
}]
- factory = SourceFactory(plugin_fixture['base'], plugins)
+ factory = SourceFactory(plugin_fixture['base'], plugin_origins=plugins)
with pytest.raises(PluginError) as exc:
foo_type = factory.lookup('foo')
@@ -233,7 +233,7 @@ def test_element_badversion(plugin_fixture, datafiles):
datafiles.basename),
'plugins': {'foo': 0}
}]
- factory = ElementFactory(plugin_fixture['base'], plugins)
+ factory = ElementFactory(plugin_fixture['base'], plugin_origins=plugins)
with pytest.raises(PluginError) as exc:
foo_type = factory.lookup('foo')
@@ -260,8 +260,8 @@ def test_source_multicontext(plugin_fixture, datafiles):
'plugins': {'foo': 0}
}
- factory1 = SourceFactory(plugin_fixture['base'], [plugins1])
- factory2 = SourceFactory(plugin_fixture['base'], [plugins2])
+ factory1 = SourceFactory(plugin_fixture['base'], plugin_origins=[plugins1])
+ factory2 = SourceFactory(plugin_fixture['base'], plugin_origins=[plugins2])
assert(isinstance(factory1, SourceFactory))
assert(isinstance(factory2, SourceFactory))
@@ -289,8 +289,8 @@ def test_element_multicontext(plugin_fixture, datafiles):
'plugins': {'foo': 0}
}
- factory1 = ElementFactory(plugin_fixture['base'], [plugins1])
- factory2 = ElementFactory(plugin_fixture['base'], [plugins2])
+ factory1 = ElementFactory(plugin_fixture['base'], plugin_origins=[plugins1])
+ factory2 = ElementFactory(plugin_fixture['base'], plugin_origins=[plugins2])
assert(isinstance(factory1, ElementFactory))
assert(isinstance(factory2, ElementFactory))
diff --git a/tests/plugins/third_party.py b/tests/plugins/third_party.py
index a786fc7c2..b7791a2e4 100644
--- a/tests/plugins/third_party.py
+++ b/tests/plugins/third_party.py
@@ -33,7 +33,8 @@ def test_custom_pip_element(plugin_fixture, entry_fixture, datafiles):
'path': str(datafiles),
'plugins': {'foop': 0}
}]
- factory = ElementFactory(plugin_fixture['base'], origin_data)
+ factory = ElementFactory(plugin_fixture['base'],
+ plugin_origins=origin_data)
assert(isinstance(factory, ElementFactory))
entry_fixture(datafiles, 'buildstream.plugins', 'third_party_element:foop')
@@ -50,7 +51,8 @@ def test_custom_pip_source(plugin_fixture, entry_fixture, datafiles):
'path': str(datafiles),
'plugins': {'foop': 0}
}]
- factory = SourceFactory(plugin_fixture['base'], origin_data)
+ factory = SourceFactory(plugin_fixture['base'],
+ plugin_origins=origin_data)
assert(isinstance(factory, SourceFactory))
entry_fixture(datafiles, 'buildstream.plugins', 'third_party_source:foop')