Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load entrypoint plugins before builtin and contrib. #1389

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 30 additions & 30 deletions src/py-opentimelineio/opentimelineio/plugins/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,10 @@ def load_manifest():

The order of loading (and precedence) is:

1. manifests specfied via the ``OTIO_PLUGIN_MANIFEST_PATH`` variable
2. builtin plugin manifest
3. contrib plugin manifest
4. ``setuptools.pkg_resources`` based plugin manifests
1. Manifests specified via the ``OTIO_PLUGIN_MANIFEST_PATH`` variable
2. Entrypoint based plugin manifests
3. Builtin plugin manifest
4. Contrib plugin manifest
"""

result = Manifest()
Expand All @@ -232,32 +232,6 @@ def load_manifest():

result.extend(manifest_from_file(json_path))

# the builtin plugin manifest
builtin_manifest_path = os.path.join(
os.path.dirname(os.path.dirname(inspect.getsourcefile(core))),
"adapters",
"builtin_adapters.plugin_manifest.json"
)
if os.path.abspath(builtin_manifest_path) not in result.source_files:
plugin_manifest = manifest_from_file(builtin_manifest_path)
result.extend(plugin_manifest)

# the contrib plugin manifest (located in the opentimelineio_contrib package)
try:
import opentimelineio_contrib as otio_c

contrib_manifest_path = os.path.join(
os.path.dirname(inspect.getsourcefile(otio_c)),
"adapters",
"contrib_adapters.plugin_manifest.json"
)
if os.path.abspath(contrib_manifest_path) not in result.source_files:
contrib_manifest = manifest_from_file(contrib_manifest_path)
result.extend(contrib_manifest)

except ImportError:
pass

# setuptools.pkg_resources based plugins
if pkg_resources:
for plugin in pkg_resources.iter_entry_points(
Expand Down Expand Up @@ -324,6 +298,32 @@ def load_manifest():
# available?
pass

# the builtin plugin manifest
builtin_manifest_path = os.path.join(
os.path.dirname(os.path.dirname(inspect.getsourcefile(core))),
"adapters",
"builtin_adapters.plugin_manifest.json"
)
if os.path.abspath(builtin_manifest_path) not in result.source_files:
plugin_manifest = manifest_from_file(builtin_manifest_path)
result.extend(plugin_manifest)

# the contrib plugin manifest (located in the opentimelineio_contrib package)
try:
import opentimelineio_contrib as otio_c

contrib_manifest_path = os.path.join(
os.path.dirname(inspect.getsourcefile(otio_c)),
"adapters",
"contrib_adapters.plugin_manifest.json"
)
if os.path.abspath(contrib_manifest_path) not in result.source_files:
contrib_manifest = manifest_from_file(contrib_manifest_path)
result.extend(contrib_manifest)

except ImportError:
pass

# force the schemadefs to load and add to schemadef module namespace
for s in result.schemadefs:
s.module()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Metadata-Version: 1.0
Name: otio-override-adapter
Version: 1.0.0
Summary: Dummy Adapter used for testing.
Home-page: http://opentimeline.io
Author: Contributors to the OpenTimelineIO project
Author-email: [email protected]
License: Modified Apache 2.0 License
Description-Content-Type: UNKNOWN
Description: UNKNOWN
Platform: any
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[opentimelineio.plugins]
mock_plugin = otio_override_adapter

Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"OTIO_SCHEMA" : "PluginManifest.1",
"adapters": [
{
"OTIO_SCHEMA" : "Adapter.1",
"name" : "cmx_3600",
"execution_scope" : "in process",
"filepath" : "adapter.py",
"suffixes" : ["edl"]
}
]
}
35 changes: 35 additions & 0 deletions tests/test_plugin_detection.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ def setUp(self):
"plugin_manifest.json"
)

self.override_adapter_manifest_path = os.path.join(
mock_module_path,
"otio_override_adapter",
"plugin_manifest.json"
)

# Create a WorkingSet as if the module were installed
entries = [mock_module_path] + pkg_resources.working_set.entries

Expand All @@ -70,6 +76,9 @@ def tearDown(self):
if 'otio_mockplugin' in sys.modules:
del sys.modules['otio_mockplugin']

if 'otio_override_adapter' in sys.modules:
del sys.modules['otio_override_adapter']

def test_detect_plugin(self):
"""This manifest uses the plugin_manifest function"""

Expand All @@ -91,6 +100,28 @@ def test_detect_plugin(self):
for linker in man.media_linkers:
self.assertIsInstance(linker, otio.media_linker.MediaLinker)

def test_overrride_adapter(self):
# Test that entrypoint plugins load before builtin and contrib
man = otio.plugins.manifest.load_manifest()

# The override_adapter creates another cmx_3600 adapter
adapters = [adapter for adapter in man.adapters
if adapter.name == "cmx_3600"]

# More then one cmx_3600 adapter should exist.
self.assertTrue(len(adapters) > 1)

# Override adapter should be the first adapter found
manifest = adapters[0].plugin_info_map().get('from manifest', None)
self.assertEqual(manifest, os.path.abspath(self.override_adapter_manifest_path))

self.assertTrue(
any(
True for p in man.source_files
if self.override_adapter_manifest_path in p
)
)

def test_pkg_resources_disabled(self):
os.environ["OTIO_DISABLE_PKG_RESOURCE_PLUGINS"] = "1"
import_reload(otio.plugins.manifest)
Expand All @@ -100,6 +131,10 @@ def test_pkg_resources_disabled(self):
with self.assertRaises(AssertionError):
self.test_detect_plugin()

# override adapter should not be loaded either
with self.assertRaises(AssertionError):
self.test_overrride_adapter()

# remove the environment variable and reload again for usage in the
# other tests
del os.environ["OTIO_DISABLE_PKG_RESOURCE_PLUGINS"]
Expand Down