mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-01 16:34:53 +01:00
Merge pull request #3731 from pypeclub/feature/module_interfaces_cleanup
General: Module interfaces cleanup
This commit is contained in:
commit
d0245ee23f
8 changed files with 111 additions and 123 deletions
|
|
@ -950,6 +950,63 @@ class ApplicationLaunchContext:
|
||||||
)
|
)
|
||||||
self.kwargs["env"] = value
|
self.kwargs["env"] = value
|
||||||
|
|
||||||
|
def _collect_addons_launch_hook_paths(self):
|
||||||
|
"""Helper to collect application launch hooks from addons.
|
||||||
|
|
||||||
|
Module have to have implemented 'get_launch_hook_paths' method which
|
||||||
|
can expect appliction as argument or nothing.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List[str]: Paths to launch hook directories.
|
||||||
|
"""
|
||||||
|
|
||||||
|
expected_types = (list, tuple, set)
|
||||||
|
|
||||||
|
output = []
|
||||||
|
for module in self.modules_manager.get_enabled_modules():
|
||||||
|
# Skip module if does not have implemented 'get_launch_hook_paths'
|
||||||
|
func = getattr(module, "get_launch_hook_paths", None)
|
||||||
|
if func is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
func = module.get_launch_hook_paths
|
||||||
|
if hasattr(inspect, "signature"):
|
||||||
|
sig = inspect.signature(func)
|
||||||
|
expect_args = len(sig.parameters) > 0
|
||||||
|
else:
|
||||||
|
expect_args = len(inspect.getargspec(func)[0]) > 0
|
||||||
|
|
||||||
|
# Pass application argument if method expect it.
|
||||||
|
try:
|
||||||
|
if expect_args:
|
||||||
|
hook_paths = func(self.application)
|
||||||
|
else:
|
||||||
|
hook_paths = func()
|
||||||
|
except Exception:
|
||||||
|
self.log.warning(
|
||||||
|
"Failed to call 'get_launch_hook_paths'",
|
||||||
|
exc_info=True
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not hook_paths:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Convert string to list
|
||||||
|
if isinstance(hook_paths, six.string_types):
|
||||||
|
hook_paths = [hook_paths]
|
||||||
|
|
||||||
|
# Skip invalid types
|
||||||
|
if not isinstance(hook_paths, expected_types):
|
||||||
|
self.log.warning((
|
||||||
|
"Result of `get_launch_hook_paths`"
|
||||||
|
" has invalid type {}. Expected {}"
|
||||||
|
).format(type(hook_paths), expected_types))
|
||||||
|
continue
|
||||||
|
|
||||||
|
output.extend(hook_paths)
|
||||||
|
return output
|
||||||
|
|
||||||
def paths_to_launch_hooks(self):
|
def paths_to_launch_hooks(self):
|
||||||
"""Directory paths where to look for launch hooks."""
|
"""Directory paths where to look for launch hooks."""
|
||||||
# This method has potential to be part of application manager (maybe).
|
# This method has potential to be part of application manager (maybe).
|
||||||
|
|
@ -983,9 +1040,7 @@ class ApplicationLaunchContext:
|
||||||
paths.append(path)
|
paths.append(path)
|
||||||
|
|
||||||
# Load modules paths
|
# Load modules paths
|
||||||
paths.extend(
|
paths.extend(self._collect_addons_launch_hook_paths())
|
||||||
self.modules_manager.collect_launch_hook_paths(self.application)
|
|
||||||
)
|
|
||||||
|
|
||||||
return paths
|
return paths
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
from .base import (
|
from .base import (
|
||||||
OpenPypeModule,
|
OpenPypeModule,
|
||||||
OpenPypeAddOn,
|
OpenPypeAddOn,
|
||||||
OpenPypeInterface,
|
|
||||||
|
|
||||||
load_modules,
|
load_modules,
|
||||||
|
|
||||||
|
|
@ -20,7 +19,6 @@ from .base import (
|
||||||
__all__ = (
|
__all__ = (
|
||||||
"OpenPypeModule",
|
"OpenPypeModule",
|
||||||
"OpenPypeAddOn",
|
"OpenPypeAddOn",
|
||||||
"OpenPypeInterface",
|
|
||||||
|
|
||||||
"load_modules",
|
"load_modules",
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,14 @@ from openpype.lib import (
|
||||||
import_module_from_dirpath
|
import_module_from_dirpath
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from .interfaces import (
|
||||||
|
OpenPypeInterface,
|
||||||
|
IPluginPaths,
|
||||||
|
IHostModule,
|
||||||
|
ITrayModule,
|
||||||
|
ITrayService
|
||||||
|
)
|
||||||
|
|
||||||
# Files that will be always ignored on modules import
|
# Files that will be always ignored on modules import
|
||||||
IGNORED_FILENAMES = (
|
IGNORED_FILENAMES = (
|
||||||
"__pycache__",
|
"__pycache__",
|
||||||
|
|
@ -389,29 +397,7 @@ def _load_modules():
|
||||||
log.error(msg, exc_info=True)
|
log.error(msg, exc_info=True)
|
||||||
|
|
||||||
|
|
||||||
class _OpenPypeInterfaceMeta(ABCMeta):
|
|
||||||
"""OpenPypeInterface meta class to print proper string."""
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "<'OpenPypeInterface.{}'>".format(self.__name__)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return str(self)
|
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(_OpenPypeInterfaceMeta)
|
|
||||||
class OpenPypeInterface:
|
|
||||||
"""Base class of Interface that can be used as Mixin with abstract parts.
|
|
||||||
|
|
||||||
This is way how OpenPype module or addon can tell that has implementation
|
|
||||||
for specific part or for other module/addon.
|
|
||||||
|
|
||||||
Child classes of OpenPypeInterface may be used as mixin in different
|
|
||||||
OpenPype modules which means they have to have implemented methods defined
|
|
||||||
in the interface. By default interface does not have any abstract parts.
|
|
||||||
"""
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(ABCMeta)
|
@six.add_metaclass(ABCMeta)
|
||||||
|
|
@ -747,8 +733,6 @@ class ModulesManager:
|
||||||
and "actions" each containing list of paths.
|
and "actions" each containing list of paths.
|
||||||
"""
|
"""
|
||||||
# Output structure
|
# Output structure
|
||||||
from openpype_interfaces import IPluginPaths
|
|
||||||
|
|
||||||
output = {
|
output = {
|
||||||
"publish": [],
|
"publish": [],
|
||||||
"create": [],
|
"create": [],
|
||||||
|
|
@ -805,8 +789,6 @@ class ModulesManager:
|
||||||
list: List of creator plugin paths.
|
list: List of creator plugin paths.
|
||||||
"""
|
"""
|
||||||
# Output structure
|
# Output structure
|
||||||
from openpype_interfaces import IPluginPaths
|
|
||||||
|
|
||||||
output = []
|
output = []
|
||||||
for module in self.get_enabled_modules():
|
for module in self.get_enabled_modules():
|
||||||
# Skip module that do not inherit from `IPluginPaths`
|
# Skip module that do not inherit from `IPluginPaths`
|
||||||
|
|
@ -821,68 +803,6 @@ class ModulesManager:
|
||||||
output.extend(paths)
|
output.extend(paths)
|
||||||
return output
|
return output
|
||||||
|
|
||||||
def collect_launch_hook_paths(self, app):
|
|
||||||
"""Helper to collect application launch hooks.
|
|
||||||
|
|
||||||
It used to be based on 'ILaunchHookPaths' which is not true anymore.
|
|
||||||
Module just have to have implemented 'get_launch_hook_paths' method.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
app (Application): Application object which can be used for
|
|
||||||
filtering of which launch hook paths are returned.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list: Paths to launch hook directories.
|
|
||||||
"""
|
|
||||||
|
|
||||||
str_type = type("")
|
|
||||||
expected_types = (list, tuple, set)
|
|
||||||
|
|
||||||
output = []
|
|
||||||
for module in self.get_enabled_modules():
|
|
||||||
# Skip module if does not have implemented 'get_launch_hook_paths'
|
|
||||||
func = getattr(module, "get_launch_hook_paths", None)
|
|
||||||
if func is None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
func = module.get_launch_hook_paths
|
|
||||||
if hasattr(inspect, "signature"):
|
|
||||||
sig = inspect.signature(func)
|
|
||||||
expect_args = len(sig.parameters) > 0
|
|
||||||
else:
|
|
||||||
expect_args = len(inspect.getargspec(func)[0]) > 0
|
|
||||||
|
|
||||||
# Pass application argument if method expect it.
|
|
||||||
try:
|
|
||||||
if expect_args:
|
|
||||||
hook_paths = func(app)
|
|
||||||
else:
|
|
||||||
hook_paths = func()
|
|
||||||
except Exception:
|
|
||||||
self.log.warning(
|
|
||||||
"Failed to call 'get_launch_hook_paths'",
|
|
||||||
exc_info=True
|
|
||||||
)
|
|
||||||
continue
|
|
||||||
|
|
||||||
if not hook_paths:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Convert string to list
|
|
||||||
if isinstance(hook_paths, str_type):
|
|
||||||
hook_paths = [hook_paths]
|
|
||||||
|
|
||||||
# Skip invalid types
|
|
||||||
if not isinstance(hook_paths, expected_types):
|
|
||||||
self.log.warning((
|
|
||||||
"Result of `get_launch_hook_paths`"
|
|
||||||
" has invalid type {}. Expected {}"
|
|
||||||
).format(type(hook_paths), expected_types))
|
|
||||||
continue
|
|
||||||
|
|
||||||
output.extend(hook_paths)
|
|
||||||
return output
|
|
||||||
|
|
||||||
def get_host_module(self, host_name):
|
def get_host_module(self, host_name):
|
||||||
"""Find host module by host name.
|
"""Find host module by host name.
|
||||||
|
|
||||||
|
|
@ -895,8 +815,6 @@ class ModulesManager:
|
||||||
host name set to passed 'host_name'.
|
host name set to passed 'host_name'.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from openpype_interfaces import IHostModule
|
|
||||||
|
|
||||||
for module in self.get_enabled_modules():
|
for module in self.get_enabled_modules():
|
||||||
if (
|
if (
|
||||||
isinstance(module, IHostModule)
|
isinstance(module, IHostModule)
|
||||||
|
|
@ -913,8 +831,6 @@ class ModulesManager:
|
||||||
inheriting 'IHostModule'.
|
inheriting 'IHostModule'.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from openpype_interfaces import IHostModule
|
|
||||||
|
|
||||||
host_names = {
|
host_names = {
|
||||||
module.host_name
|
module.host_name
|
||||||
for module in self.get_enabled_modules()
|
for module in self.get_enabled_modules()
|
||||||
|
|
@ -1096,8 +1012,6 @@ class TrayModulesManager(ModulesManager):
|
||||||
self.tray_menu(tray_menu)
|
self.tray_menu(tray_menu)
|
||||||
|
|
||||||
def get_enabled_tray_modules(self):
|
def get_enabled_tray_modules(self):
|
||||||
from openpype_interfaces import ITrayModule
|
|
||||||
|
|
||||||
output = []
|
output = []
|
||||||
for module in self.modules:
|
for module in self.modules:
|
||||||
if module.enabled and isinstance(module, ITrayModule):
|
if module.enabled and isinstance(module, ITrayModule):
|
||||||
|
|
@ -1173,8 +1087,6 @@ class TrayModulesManager(ModulesManager):
|
||||||
self._report["Tray menu"] = report
|
self._report["Tray menu"] = report
|
||||||
|
|
||||||
def start_modules(self):
|
def start_modules(self):
|
||||||
from openpype_interfaces import ITrayService
|
|
||||||
|
|
||||||
report = {}
|
report = {}
|
||||||
time_start = time.time()
|
time_start = time.time()
|
||||||
prev_start_time = time_start
|
prev_start_time = time_start
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ from openpype.modules import OpenPypeModule
|
||||||
from openpype_interfaces import (
|
from openpype_interfaces import (
|
||||||
ITrayModule,
|
ITrayModule,
|
||||||
IPluginPaths,
|
IPluginPaths,
|
||||||
ILaunchHookPaths,
|
|
||||||
ISettingsChangeListener
|
ISettingsChangeListener
|
||||||
)
|
)
|
||||||
from openpype.settings import SaveWarningExc
|
from openpype.settings import SaveWarningExc
|
||||||
|
|
@ -21,7 +20,6 @@ class FtrackModule(
|
||||||
OpenPypeModule,
|
OpenPypeModule,
|
||||||
ITrayModule,
|
ITrayModule,
|
||||||
IPluginPaths,
|
IPluginPaths,
|
||||||
ILaunchHookPaths,
|
|
||||||
ISettingsChangeListener
|
ISettingsChangeListener
|
||||||
):
|
):
|
||||||
name = "ftrack"
|
name = "ftrack"
|
||||||
|
|
@ -85,7 +83,8 @@ class FtrackModule(
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_launch_hook_paths(self):
|
def get_launch_hook_paths(self):
|
||||||
"""Implementation of `ILaunchHookPaths`."""
|
"""Implementation for applications launch hooks."""
|
||||||
|
|
||||||
return os.path.join(FTRACK_MODULE_DIR, "launch_hooks")
|
return os.path.join(FTRACK_MODULE_DIR, "launch_hooks")
|
||||||
|
|
||||||
def modify_application_launch_arguments(self, application, env):
|
def modify_application_launch_arguments(self, application, env):
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,33 @@
|
||||||
from abc import abstractmethod, abstractproperty
|
from abc import ABCMeta, abstractmethod, abstractproperty
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
from openpype import resources
|
from openpype import resources
|
||||||
|
|
||||||
from openpype.modules import OpenPypeInterface
|
|
||||||
|
class _OpenPypeInterfaceMeta(ABCMeta):
|
||||||
|
"""OpenPypeInterface meta class to print proper string."""
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "<'OpenPypeInterface.{}'>".format(self.__name__)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return str(self)
|
||||||
|
|
||||||
|
|
||||||
|
@six.add_metaclass(_OpenPypeInterfaceMeta)
|
||||||
|
class OpenPypeInterface:
|
||||||
|
"""Base class of Interface that can be used as Mixin with abstract parts.
|
||||||
|
|
||||||
|
This is way how OpenPype module or addon can tell OpenPype that contain
|
||||||
|
implementation for specific functionality.
|
||||||
|
|
||||||
|
Child classes of OpenPypeInterface may be used as mixin in different
|
||||||
|
OpenPype modules which means they have to have implemented methods defined
|
||||||
|
in the interface. By default interface does not have any abstract parts.
|
||||||
|
"""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class IPluginPaths(OpenPypeInterface):
|
class IPluginPaths(OpenPypeInterface):
|
||||||
|
|
@ -56,6 +81,13 @@ class ILaunchHookPaths(OpenPypeInterface):
|
||||||
|
|
||||||
Expected result is list of paths.
|
Expected result is list of paths.
|
||||||
["path/to/launch_hooks_dir"]
|
["path/to/launch_hooks_dir"]
|
||||||
|
|
||||||
|
Deprecated:
|
||||||
|
This interface is not needed since OpenPype 3.14.*. Addon just have to
|
||||||
|
implement 'get_launch_hook_paths' which can expect Application object
|
||||||
|
or nothing as argument.
|
||||||
|
|
||||||
|
Interface class will be removed after 3.16.*.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ import os
|
||||||
from openpype_interfaces import (
|
from openpype_interfaces import (
|
||||||
ITrayModule,
|
ITrayModule,
|
||||||
IPluginPaths,
|
IPluginPaths,
|
||||||
ILaunchHookPaths,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
from openpype.modules import OpenPypeModule
|
from openpype.modules import OpenPypeModule
|
||||||
|
|
@ -11,9 +10,7 @@ from openpype.modules import OpenPypeModule
|
||||||
SHOTGRID_MODULE_DIR = os.path.dirname(os.path.abspath(__file__))
|
SHOTGRID_MODULE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
|
||||||
class ShotgridModule(
|
class ShotgridModule(OpenPypeModule, ITrayModule, IPluginPaths):
|
||||||
OpenPypeModule, ITrayModule, IPluginPaths, ILaunchHookPaths
|
|
||||||
):
|
|
||||||
leecher_manager_url = None
|
leecher_manager_url = None
|
||||||
name = "shotgrid"
|
name = "shotgrid"
|
||||||
enabled = False
|
enabled = False
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,11 @@
|
||||||
import os
|
import os
|
||||||
from openpype.modules import OpenPypeModule
|
from openpype.modules import OpenPypeModule
|
||||||
from openpype_interfaces import (
|
from openpype.modules.interfaces import IPluginPaths
|
||||||
IPluginPaths,
|
|
||||||
ILaunchHookPaths
|
|
||||||
)
|
|
||||||
|
|
||||||
SLACK_MODULE_DIR = os.path.dirname(os.path.abspath(__file__))
|
SLACK_MODULE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
|
||||||
class SlackIntegrationModule(OpenPypeModule, IPluginPaths, ILaunchHookPaths):
|
class SlackIntegrationModule(OpenPypeModule, IPluginPaths):
|
||||||
"""Allows sending notification to Slack channels during publishing."""
|
"""Allows sending notification to Slack channels during publishing."""
|
||||||
|
|
||||||
name = "slack"
|
name = "slack"
|
||||||
|
|
@ -18,7 +15,8 @@ class SlackIntegrationModule(OpenPypeModule, IPluginPaths, ILaunchHookPaths):
|
||||||
self.enabled = slack_settings["enabled"]
|
self.enabled = slack_settings["enabled"]
|
||||||
|
|
||||||
def get_launch_hook_paths(self):
|
def get_launch_hook_paths(self):
|
||||||
"""Implementation of `ILaunchHookPaths`."""
|
"""Implementation for applications launch hooks."""
|
||||||
|
|
||||||
return os.path.join(SLACK_MODULE_DIR, "launch_hooks")
|
return os.path.join(SLACK_MODULE_DIR, "launch_hooks")
|
||||||
|
|
||||||
def get_plugin_paths(self):
|
def get_plugin_paths(self):
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ from openpype.client import get_asset_by_name
|
||||||
from openpype.modules import OpenPypeModule
|
from openpype.modules import OpenPypeModule
|
||||||
from openpype_interfaces import (
|
from openpype_interfaces import (
|
||||||
ITrayService,
|
ITrayService,
|
||||||
ILaunchHookPaths,
|
|
||||||
IPluginPaths
|
IPluginPaths
|
||||||
)
|
)
|
||||||
from openpype.lib.events import register_event_callback
|
from openpype.lib.events import register_event_callback
|
||||||
|
|
@ -79,7 +78,6 @@ class ExampleTimersManagerConnector:
|
||||||
class TimersManager(
|
class TimersManager(
|
||||||
OpenPypeModule,
|
OpenPypeModule,
|
||||||
ITrayService,
|
ITrayService,
|
||||||
ILaunchHookPaths,
|
|
||||||
IPluginPaths
|
IPluginPaths
|
||||||
):
|
):
|
||||||
""" Handles about Timers.
|
""" Handles about Timers.
|
||||||
|
|
@ -185,12 +183,11 @@ class TimersManager(
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_launch_hook_paths(self):
|
def get_launch_hook_paths(self):
|
||||||
"""Implementation of `ILaunchHookPaths`."""
|
"""Implementation for applications launch hooks."""
|
||||||
|
|
||||||
return os.path.join(
|
return [
|
||||||
TIMER_MODULE_DIR,
|
os.path.join(TIMER_MODULE_DIR, "launch_hooks")
|
||||||
"launch_hooks"
|
]
|
||||||
)
|
|
||||||
|
|
||||||
def get_plugin_paths(self):
|
def get_plugin_paths(self):
|
||||||
"""Implementation of `IPluginPaths`."""
|
"""Implementation of `IPluginPaths`."""
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue