diff --git a/src/rez/plugin_managers.py b/src/rez/plugin_managers.py index 20ce8a873..dbcab4eb8 100644 --- a/src/rez/plugin_managers.py +++ b/src/rez/plugin_managers.py @@ -73,6 +73,11 @@ def append_if_valid(dir_): return path +def uncache_sys_module_paths(instance=None): + instance = instance or plugin_manager + cached_property.uncache(instance, "sys_module_paths") + + class RezPluginType(object): """An abstract base class representing a single type of plugin. diff --git a/src/rez/tests/data/extensions/bar/__init__.py b/src/rez/tests/data/extensions/bar/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/rez/tests/data/extensions/bar/rezplugins/__init__.py b/src/rez/tests/data/extensions/bar/rezplugins/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/rez/tests/data/extensions/bar/rezplugins/package_repository/__init__.py b/src/rez/tests/data/extensions/bar/rezplugins/package_repository/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/rez/tests/data/extensions/bar/rezplugins/package_repository/memory.py b/src/rez/tests/data/extensions/bar/rezplugins/package_repository/memory.py new file mode 100644 index 000000000..4a0a72437 --- /dev/null +++ b/src/rez/tests/data/extensions/bar/rezplugins/package_repository/memory.py @@ -0,0 +1,13 @@ + +from rez.package_repository import PackageRepository + + +class MemoryPackageRepository(PackageRepository): + @classmethod + def name(cls): + return "memory" + on_test = "bar" + + +def register_plugin(): + return MemoryPackageRepository diff --git a/src/rez/tests/data/extensions/foo/__init__.py b/src/rez/tests/data/extensions/foo/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/rez/tests/data/extensions/foo/rezplugins/__init__.py b/src/rez/tests/data/extensions/foo/rezplugins/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/rez/tests/data/extensions/foo/rezplugins/package_repository/__init__.py b/src/rez/tests/data/extensions/foo/rezplugins/package_repository/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/rez/tests/data/extensions/foo/rezplugins/package_repository/cloud.py b/src/rez/tests/data/extensions/foo/rezplugins/package_repository/cloud.py new file mode 100644 index 000000000..f5729a185 --- /dev/null +++ b/src/rez/tests/data/extensions/foo/rezplugins/package_repository/cloud.py @@ -0,0 +1,12 @@ + +from rez.package_repository import PackageRepository + + +class CloudPackageRepository(PackageRepository): + @classmethod + def name(cls): + return "cloud" + + +def register_plugin(): + return CloudPackageRepository diff --git a/src/rez/tests/data/extensions/non-mod/rezplugins/__init__.py b/src/rez/tests/data/extensions/non-mod/rezplugins/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/rez/tests/data/extensions/non-mod/rezplugins/package_repository/__init__.py b/src/rez/tests/data/extensions/non-mod/rezplugins/package_repository/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/rez/tests/data/extensions/non-mod/rezplugins/package_repository/memory.py b/src/rez/tests/data/extensions/non-mod/rezplugins/package_repository/memory.py new file mode 100644 index 000000000..263081007 --- /dev/null +++ b/src/rez/tests/data/extensions/non-mod/rezplugins/package_repository/memory.py @@ -0,0 +1,13 @@ + +from rez.package_repository import PackageRepository + + +class MemoryPackageRepository(PackageRepository): + @classmethod + def name(cls): + return "memory" + on_test = "non-mod" + + +def register_plugin(): + return MemoryPackageRepository diff --git a/src/rez/tests/test_plugin_manager.py b/src/rez/tests/test_plugin_manager.py new file mode 100644 index 000000000..a5a73d99f --- /dev/null +++ b/src/rez/tests/test_plugin_manager.py @@ -0,0 +1,112 @@ +""" +test rezplugins manager behaviors +""" +from rez.tests.util import TestBase, TempdirMixin, restore_sys_path +from rez.plugin_managers import ( + uncache_sys_module_paths, + RezPluginManager, + ShellPluginType, + ReleaseVCSPluginType, + ReleaseHookPluginType, + BuildSystemPluginType, + PackageRepositoryPluginType, + BuildProcessPluginType, + CommandPluginType +) +import os +import sys +import unittest + + +class TestPluginManagers(TestBase, TempdirMixin): + def __init__(self, *nargs, **kwargs): + TestBase.__init__(self, *nargs, **kwargs) + self._original_modules = set() + self.plugin_manager = None + + def setUp(self): + TestBase.setUp(self) + uncache_sys_module_paths() + + plugin_manager = RezPluginManager() + plugin_manager.register_plugin_type(ShellPluginType) + plugin_manager.register_plugin_type(ReleaseVCSPluginType) + plugin_manager.register_plugin_type(ReleaseHookPluginType) + plugin_manager.register_plugin_type(BuildSystemPluginType) + plugin_manager.register_plugin_type(PackageRepositoryPluginType) + plugin_manager.register_plugin_type(BuildProcessPluginType) + plugin_manager.register_plugin_type(CommandPluginType) + + self._original_modules.update(sys.modules.keys()) + self.plugin_manager = plugin_manager + + def tearDown(self): + TestBase.tearDown(self) + self.plugin_manager = None + + for key in set(sys.modules.keys()): + if key not in self._original_modules: + del sys.modules[key] + self._original_modules.clear() + + def test_old_loading_style(self): + """Test loading rez plugin from plugin_path""" + path = os.path.realpath(os.path.dirname(__file__)) + self.update_settings(dict( + plugin_path=[os.path.join(path, "data", "extensions", "foo")] + )) + + cloud_cls = self.plugin_manager.get_plugin_class( + "package_repository", "cloud") + self.assertEqual(cloud_cls.name(), "cloud") + + def test_new_loading_style(self): + """Test loading rez plugin from python modules""" + path = os.path.realpath(os.path.dirname(__file__)) + with restore_sys_path(): + sys.path.append(os.path.join(path, "data", "extensions")) + + cloud_cls = self.plugin_manager.get_plugin_class( + "package_repository", "cloud") + self.assertEqual(cloud_cls.name(), "cloud") + + def test_plugin_override_1(self): + """Test plugin from plugin_path can override the default""" + path = os.path.realpath(os.path.dirname(__file__)) + self.update_settings(dict( + plugin_path=[os.path.join(path, "data", "extensions", "non-mod")] + )) + + mem_cls = self.plugin_manager.get_plugin_class( + "package_repository", "memory") + self.assertEqual("non-mod", mem_cls.on_test) + + def test_plugin_override_2(self): + """Test plugin from python modules can override the default""" + path = os.path.realpath(os.path.dirname(__file__)) + with restore_sys_path(): + sys.path.append(os.path.join(path, "data", "extensions")) + + mem_cls = self.plugin_manager.get_plugin_class( + "package_repository", "memory") + self.assertEqual("bar", mem_cls.on_test) + + def test_plugin_override_3(self): + """Test plugin from python modules can override plugin_path""" + path = os.path.realpath(os.path.dirname(__file__)) + with restore_sys_path(): + # setup new + sys.path.append(os.path.join(path, "data", "extensions")) + # setup old + self.update_settings(dict( + plugin_path=[os.path.join(path, "data", "extensions", "non-mod")] + )) + + mem_cls = self.plugin_manager.get_plugin_class( + "package_repository", "memory") + self.assertEqual("bar", mem_cls.on_test) + + +if __name__ == '__main__': + unittest.main() +