From 636b5eaead345be0ca036b093c00d678e443968f Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 15 Dec 2020 13:37:40 +0100 Subject: [PATCH 01/13] implemented `ITrayAction` --- pype/modules/base.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/pype/modules/base.py b/pype/modules/base.py index 3c2c2e7e21..074fd43429 100644 --- a/pype/modules/base.py +++ b/pype/modules/base.py @@ -124,6 +124,41 @@ class ITrayModule: pass +class ITrayAction(ITrayModule): + """Implementation of Tray action. + + Add action to tray menu which will trigger `on_action_trigger`. + It is expected to be used for showing tools. + + Methods `tray_start`, `tray_exit` and `connect_with_modules` are overriden + as it's not expected that action will use them. But it is possible if + necessary. + """ + + @property + @abstractmethod + def label(self): + """Service label showed in menu.""" + pass + + @abstractmethod + def on_action_trigger(self): + """What happens on actions click.""" + pass + + def tray_menu(self, tray_menu): + from Qt import QtWidgets + action = QtWidgets.QAction(self.label, tray_menu) + action.triggered.connect(self.on_action_trigger) + tray_menu.addAction(action) + + def tray_start(self): + return + + def tray_exit(self): + return + + class ITrayService(ITrayModule): # Module's property menu_action = None From 7b54264804a2cf8ae4278a7a1b0e43cc4ae58da1 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 15 Dec 2020 13:38:26 +0100 Subject: [PATCH 02/13] SettingsModule renamed to SettingsAction and inherit from ITrayAction instead of ITrayModule --- ...{settings_module.py => settings_action.py} | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) rename pype/modules/{settings_module.py => settings_action.py} (58%) diff --git a/pype/modules/settings_module.py b/pype/modules/settings_action.py similarity index 58% rename from pype/modules/settings_module.py rename to pype/modules/settings_action.py index 0651170148..0d56a6c5ae 100644 --- a/pype/modules/settings_module.py +++ b/pype/modules/settings_action.py @@ -1,11 +1,13 @@ -from . import PypeModule, ITrayModule +from . import PypeModule, ITrayAction -class SettingsModule(PypeModule, ITrayModule): +class SettingsAction(PypeModule, ITrayAction): + """Action to show Setttings tool.""" name = "settings" + label = "Settings" def initialize(self, _modules_settings): - # This module is always enabled + # This action is always enabled self.enabled = True # User role @@ -18,13 +20,28 @@ class SettingsModule(PypeModule, ITrayModule): def connect_with_modules(self, *_a, **_kw): return + def tray_init(self): + """Initialization in tray implementation of ITrayAction.""" + self.create_settings_window() + + def on_action_trigger(self): + """Implementation for action trigger of ITrayAction.""" + self.show_settings_window() + def create_settings_window(self): + """Initializa Settings Qt window.""" if self.settings_window: return from pype.tools.settings import MainWidget self.settings_window = MainWidget(self.user_role) def show_settings_window(self): + """Show settings tool window. + + Raises: + AssertionError: Window must be already created. Call + `create_settings_window` before callint this method. + """ if not self.settings_window: raise AssertionError("Window is not initialized.") @@ -33,21 +50,3 @@ class SettingsModule(PypeModule, ITrayModule): # Pull window to the front. self.settings_window.raise_() self.settings_window.activateWindow() - - def tray_init(self): - self.create_settings_window() - - def tray_menu(self, tray_menu): - """Add **change credentials** option to tray menu.""" - from Qt import QtWidgets - - # Actions - action = QtWidgets.QAction("Settings", tray_menu) - action.triggered.connect(self.show_settings_window) - tray_menu.addAction(action) - - def tray_start(self): - return - - def tray_exit(self): - return From dd5dea2c04476c9206e29c23060ff92c4a3f708c Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 15 Dec 2020 13:38:40 +0100 Subject: [PATCH 03/13] converted StandAlonePublishModule to StandAlonePublishAction --- pype/modules/standalonepublish/__init__.py | 5 ----- ..._module.py => standalonepublish_action.py} | 19 +++++-------------- 2 files changed, 5 insertions(+), 19 deletions(-) delete mode 100644 pype/modules/standalonepublish/__init__.py rename pype/modules/{standalonepublish/standalonepublish_module.py => standalonepublish_action.py} (70%) diff --git a/pype/modules/standalonepublish/__init__.py b/pype/modules/standalonepublish/__init__.py deleted file mode 100644 index 5c40deb6f0..0000000000 --- a/pype/modules/standalonepublish/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from .standalonepublish_module import StandAlonePublishModule - -__all__ = ( - "StandAlonePublishModule", -) diff --git a/pype/modules/standalonepublish/standalonepublish_module.py b/pype/modules/standalonepublish_action.py similarity index 70% rename from pype/modules/standalonepublish/standalonepublish_module.py rename to pype/modules/standalonepublish_action.py index 5b0cfe14bf..0e7bcfd86e 100644 --- a/pype/modules/standalonepublish/standalonepublish_module.py +++ b/pype/modules/standalonepublish_action.py @@ -1,15 +1,15 @@ import os import sys import subprocess -import pype -from .. import PypeModule, ITrayModule +from . import PypeModule, ITrayAction -class StandAlonePublishModule(PypeModule, ITrayModule): +class StandAlonePublishAction(PypeModule, ITrayAction): menu_label = "Publish" name = "standalonepublish_tool" def initialize(self, modules_settings): + import pype self.enabled = modules_settings[self.name]["enabled"] self.publish_paths = [ os.path.join( @@ -20,17 +20,8 @@ class StandAlonePublishModule(PypeModule, ITrayModule): def tray_init(self): return - def tray_start(self): - return - - def tray_exit(self): - return - - def tray_menu(self, parent_menu): - from Qt import QtWidgets - run_action = QtWidgets.QAction(self.menu_label, parent_menu) - run_action.triggered.connect(self.run_standalone_publisher) - parent_menu.addAction(run_action) + def on_action_trigger(self): + self.run_standalone_publisher() def connect_with_modules(self, enabled_modules): """Collect publish paths from other modules.""" From 5db24e34ae9860a1518c4000319a507d97fc0564 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 15 Dec 2020 13:39:17 +0100 Subject: [PATCH 04/13] extracted launcher from avalon module to launcher action --- pype/modules/avalon_apps/avalon_app.py | 33 +------------------- pype/modules/base.py | 1 + pype/modules/launcher_action.py | 43 ++++++++++++++++++++++++++ pype/tools/launcher/actions.py | 14 ++++++--- 4 files changed, 54 insertions(+), 37 deletions(-) create mode 100644 pype/modules/launcher_action.py diff --git a/pype/modules/avalon_apps/avalon_app.py b/pype/modules/avalon_apps/avalon_app.py index 683d804412..d00a306e9e 100644 --- a/pype/modules/avalon_apps/avalon_app.py +++ b/pype/modules/avalon_apps/avalon_app.py @@ -44,7 +44,6 @@ class AvalonModule(PypeModule, ITrayModule, IRestApi): ) # Tray attributes - self.app_launcher = None self.libraryloader = None self.rest_api_obj = None @@ -99,29 +98,8 @@ class AvalonModule(PypeModule, ITrayModule, IRestApi): exc_info=True ) - # Add launcher - try: - from pype.tools.launcher import LauncherWindow - self.app_launcher = LauncherWindow() - except Exception: - self.log.warning( - "Couldn't load Launch for tray.", - exc_info=True - ) - def connect_with_modules(self, _enabled_modules): - plugin_paths = self.manager.collect_plugin_paths()["actions"] - if plugin_paths: - env_paths_str = os.environ.get("AVALON_ACTIONS") or "" - env_paths = env_paths_str.split(os.pathsep) - env_paths.extend(plugin_paths) - os.environ["AVALON_ACTIONS"] = os.pathsep.join(env_paths) - - if self.tray_initialized: - from pype.tools.launcher import actions - # actions.register_default_actions() - actions.register_config_actions() - actions.register_environment_actions() + return def rest_api_initialization(self, rest_api_module): if self.tray_initialized: @@ -132,15 +110,12 @@ class AvalonModule(PypeModule, ITrayModule, IRestApi): def tray_menu(self, tray_menu): from Qt import QtWidgets # Actions - action_launcher = QtWidgets.QAction("Launcher", tray_menu) action_library_loader = QtWidgets.QAction( "Library loader", tray_menu ) - action_launcher.triggered.connect(self.show_launcher) action_library_loader.triggered.connect(self.show_library_loader) - tray_menu.addAction(action_launcher) tray_menu.addAction(action_library_loader) def tray_start(self, *_a, **_kw): @@ -149,12 +124,6 @@ class AvalonModule(PypeModule, ITrayModule, IRestApi): def tray_exit(self, *_a, **_kw): return - def show_launcher(self): - # if app_launcher don't exist create it/otherwise only show main window - self.app_launcher.show() - self.app_launcher.raise_() - self.app_launcher.activateWindow() - def show_library_loader(self): self.libraryloader.show() diff --git a/pype/modules/base.py b/pype/modules/base.py index 074fd43429..43ed570e19 100644 --- a/pype/modules/base.py +++ b/pype/modules/base.py @@ -422,6 +422,7 @@ class TrayModulesManager(ModulesManager): "user", "ftrack", "muster", + "launcher_tool", "avalon", "clockify", "standalonepublish_tool", diff --git a/pype/modules/launcher_action.py b/pype/modules/launcher_action.py new file mode 100644 index 0000000000..bc6ad507c4 --- /dev/null +++ b/pype/modules/launcher_action.py @@ -0,0 +1,43 @@ +from . import PypeModule, ITrayAction + + +class LauncherAction(PypeModule, ITrayAction): + label = "Launcher" + name = "launcher_tool" + + def initialize(self, _modules_settings): + # This module is always enabled + self.enabled = True + + # Tray attributes + self.window = None + + def tray_init(self): + self.create_window() + + def tray_start(self): + # Register actions + from pype.tools.launcher import actions + # actions.register_default_actions() + actions.register_config_actions() + actions_paths = self.manager.collect_plugin_paths()["actions"] + actions.register_actions_from_paths(actions_paths) + actions.register_environment_actions() + + def connect_with_modules(self, _enabled_modules): + return + + def create_window(self): + if self.window: + return + from pype.tools.launcher import LauncherWindow + self.window = LauncherWindow() + + def on_action_trigger(self): + self.show_launcher() + + def show_launcher(self): + if self.window: + self.window.show() + self.window.raise_() + self.window.activateWindow() diff --git a/pype/tools/launcher/actions.py b/pype/tools/launcher/actions.py index 6d0c94b676..db50c0c859 100644 --- a/pype/tools/launcher/actions.py +++ b/pype/tools/launcher/actions.py @@ -85,14 +85,11 @@ def register_config_actions(): config.register_launcher_actions() -def register_environment_actions(): - """Register actions from AVALON_ACTIONS for Launcher.""" - - paths = os.environ.get("AVALON_ACTIONS") +def register_actions_from_paths(paths): if not paths: return - for path in paths.split(os.pathsep): + for path in paths: api.register_plugin_path(api.Action, path) # Run "register" if found. @@ -110,6 +107,13 @@ def register_environment_actions(): ) +def register_environment_actions(): + """Register actions from AVALON_ACTIONS for Launcher.""" + + paths = os.environ.get("AVALON_ACTIONS") or "" + register_actions_from_paths(paths.split(os.pathsep)) + + class ApplicationAction(api.Action): """Pype's application launcher From 98a745c7135d44bce110efd61e21d84c492ba81a Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 15 Dec 2020 13:39:34 +0100 Subject: [PATCH 05/13] added readme --- pype/modules/README.md | 103 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 pype/modules/README.md diff --git a/pype/modules/README.md b/pype/modules/README.md new file mode 100644 index 0000000000..818375461f --- /dev/null +++ b/pype/modules/README.md @@ -0,0 +1,103 @@ +# Pype modules +Pype modules should contain separated logic of specific kind of implementation, like Ftrack connection and usage code or Deadline farm rendering. + +## Base class `PypeModule` +- abstract class as base for each module +- implementation should be module's api withou GUI parts +- may implement `get_global_environments` method which should return dictionary of environments that are globally appliable and value is the same for whole studio if launched at any workstation (except os specific paths) +- abstract parts: + - `name` attribute - name of a module + - `initialize` method - method for own initialization of a module (should not override `__init__`) + - `connect_with_modules` method - where module may look for it's interfaces implementations or check for other modules +- `__init__` should not be overriden and `initialize` should not do time consuming part but only prepare base data about module + - also keep in mind that they may be initialized in headless mode +- connection with other modules is made with help of interfaces + +# Interfaces +- interface is class that has defined abstract methods to implement and may contain preimplemented helper methods +- module that inherit from an interface must implement those abstract methods otherwise won't be initialized +- it is easy to find which module object inherited from which interfaces withh 100% chance they have implemented required methods + +## Global interfaces +- few interfaces are implemented for global usage + +### IPluginPaths +- module want to add directory path/s to avalon or publish plugins +- module must implement `get_plugin_paths` which must return dictionary with possible keys `"publish"`, `"load"`, `"create"` or `"actions"` + - each key may contain list or string with path to directory with plugins + +### ITrayModule +- module has more logic when used in tray + - it is possible that module can be used only in tray +- abstract methods + - `tray_init` - initialization triggered after `initialize` when used in `TrayModulesManager` and before `connect_with_modules` + - `tray_menu` - add actions to tray widget's menu that represent the module + - `tray_start` - start of module's login in tray + - module is initialized and connected with other modules + - `tray_exit` - module's cleanup like stop and join threads etc. + - order of calling is based on implementation this order is how it works with `TrayModulesManager` + - it is recommended to import and use GUI implementaion only in these methods +- has attribute `tray_initialized` (bool) which is set to False by default and is set by `TrayModulesManager` to True after `tray_init` + - if module has logic only in tray or for both then should be checking for `tray_initialized` attribute to decide how should handle situations + +### ITrayService +- inherit from `ITrayModule` and implement `tray_menu` method for you + - add action to submenu "Services" in tray widget menu with icon and label +- abstract atttribute `label` + - label shown in menu +- interface has preimplemented methods to change icon color + - `set_service_running` - green icon + - `set_service_failed` - red icon + - `set_service_idle` - orange icon + - these states must be set by module itself `set_service_running` is default state on initialization + +### ITrayAction +- inherit from `ITrayModule` and implement `tray_menu` method for you + - add action to tray widget menu with label +- abstract atttribute `label` + - label shown in menu +- abstract method `on_action_trigger` + - what should happen when action is triggered +- NOTE: It is good idea to implement logic in `on_action_trigger` to api method and trigger that methods on callbacks this gives ability to trigger that method outside tray + +## Modules interfaces +- modules may have defined their interfaces to be able recognize other modules that would want to use their features +- +### Example: +- Ftrack module has `IFtrackEventHandlerPaths` which helps to tell Ftrack module which of other modules want to add paths to server/user event handlers + - Clockify module use `IFtrackEventHandlerPaths` and return paths to clockify ftrack synchronizers + +- Clockify has more inharitance it's class definition looks like +``` +class ClockifyModule( + PypeModule, # Says it's Pype module so ModulesManager will try to initialize. + ITrayModule, # Says has special implementation when used in tray. + IPluginPaths, # Says has plugin paths that want to register (paths to clockify actions for launcher). + IFtrackEventHandlerPaths, # Says has Ftrack actions/events for user/server. + ITimersManager # Listen to other modules with timer and can trigger changes in other module timers through `TimerManager` module. +): +``` + +### ModulesManager +- collect module classes and tries to initialize them +- important attributes + - `modules` - list of available attributes + - `modules_by_id` - dictionary of modules mapped by their ids + - `modules_by_name` - dictionary of modules mapped by their names + - all these attributes contain all found modules even if are not enabled +- helper methods + - `collect_global_environments` to collect all global environments from enabled modules with calling `get_global_environments` on each of them + - `collect_plugin_paths` collect plugin paths from all enabled modules + - output is always dictionary with all keys and values as list + ``` + { + "publish": [], + "create": [], + "load": [], + "actions": [] + } + ``` + +### TrayModulesManager +- inherit from `ModulesManager` +- has specific implementations for Pype Tray tool and handle `ITrayModule` methods From 7153f131b6e8f2535e57ddaacce0c13d94fe5f70 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 15 Dec 2020 13:39:40 +0100 Subject: [PATCH 06/13] fix imports --- pype/modules/__init__.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pype/modules/__init__.py b/pype/modules/__init__.py index 00303aafc6..49e158b55e 100644 --- a/pype/modules/__init__.py +++ b/pype/modules/__init__.py @@ -2,12 +2,13 @@ from .base import ( PypeModule, ITrayModule, + ITrayAction, ITrayService, IPluginPaths, ModulesManager, TrayModulesManager ) -from .settings_module import SettingsModule +from .settings_action import SettingsAction from .rest_api import ( RestApiModule, IRestApi @@ -25,6 +26,7 @@ from .timers_manager import ( ITimersManager ) from .avalon_apps import AvalonModule +from .launcher_action import LauncherAction from .ftrack import ( FtrackModule, IFtrackEventHandlerPaths @@ -32,19 +34,20 @@ from .ftrack import ( from .clockify import ClockifyModule from .logging import LoggingModule from .muster import MusterModule -from .standalonepublish import StandAlonePublishModule +from .standalonepublish_action import StandAlonePublishAction from .websocket_server import WebsocketModule __all__ = ( "PypeModule", "ITrayModule", + "ITrayAction", "ITrayService", "IPluginPaths", "ModulesManager", "TrayModulesManager", - "SettingsModule", + "SettingsAction", "UserModule", "IUserModule", @@ -59,6 +62,7 @@ __all__ = ( "IRestApi", "AvalonModule", + "LauncherAction", "FtrackModule", "IFtrackEventHandlerPaths", @@ -67,7 +71,7 @@ __all__ = ( "IdleManager", "LoggingModule", "MusterModule", - "StandAlonePublishModule", + "StandAlonePublishAction", "WebsocketModule" ) From 29cf951ecf6f0978d9a354536a978a21d5656005 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 15 Dec 2020 17:43:45 +0100 Subject: [PATCH 07/13] fix standalone publish label --- pype/modules/standalonepublish_action.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/modules/standalonepublish_action.py b/pype/modules/standalonepublish_action.py index 0e7bcfd86e..4bcb5b6018 100644 --- a/pype/modules/standalonepublish_action.py +++ b/pype/modules/standalonepublish_action.py @@ -5,7 +5,7 @@ from . import PypeModule, ITrayAction class StandAlonePublishAction(PypeModule, ITrayAction): - menu_label = "Publish" + label = "Publish" name = "standalonepublish_tool" def initialize(self, modules_settings): From d0e3caacf4ff0ac0e4576ddde0133c62a02e5269 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 15 Dec 2020 17:56:44 +0100 Subject: [PATCH 08/13] moved registering of action to different spot because it cases huge issues when happens in `tray_start` --- pype/modules/launcher_action.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/pype/modules/launcher_action.py b/pype/modules/launcher_action.py index bc6ad507c4..9c2120cf9a 100644 --- a/pype/modules/launcher_action.py +++ b/pype/modules/launcher_action.py @@ -16,17 +16,18 @@ class LauncherAction(PypeModule, ITrayAction): self.create_window() def tray_start(self): - # Register actions - from pype.tools.launcher import actions - # actions.register_default_actions() - actions.register_config_actions() - actions_paths = self.manager.collect_plugin_paths()["actions"] - actions.register_actions_from_paths(actions_paths) - actions.register_environment_actions() - - def connect_with_modules(self, _enabled_modules): return + def connect_with_modules(self, enabled_modules): + # Register actions + if self.tray_initialized: + from pype.tools.launcher import actions + # actions.register_default_actions() + actions.register_config_actions() + actions_paths = self.manager.collect_plugin_paths()["actions"] + actions.register_actions_from_paths(actions_paths) + actions.register_environment_actions() + def create_window(self): if self.window: return From f7ed24889252d9c17fea82a68c02659c0d97e254 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 17 Dec 2020 10:46:08 +0100 Subject: [PATCH 09/13] fixed environment paths registering --- pype/tools/launcher/actions.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pype/tools/launcher/actions.py b/pype/tools/launcher/actions.py index db50c0c859..5d52b44acd 100644 --- a/pype/tools/launcher/actions.py +++ b/pype/tools/launcher/actions.py @@ -110,8 +110,13 @@ def register_actions_from_paths(paths): def register_environment_actions(): """Register actions from AVALON_ACTIONS for Launcher.""" - paths = os.environ.get("AVALON_ACTIONS") or "" - register_actions_from_paths(paths.split(os.pathsep)) + paths_str = os.environ.get("AVALON_ACTIONS") or "" + paths = [] + for path in paths_str.split(os.pathsep): + if path and os.path.exists(path): + paths.append(path) + + register_actions_from_paths(paths) class ApplicationAction(api.Action): From 2c70a160e0d936cb75973f517ae50ef44ad1b878 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 17 Dec 2020 10:52:04 +0100 Subject: [PATCH 10/13] added try except in connect with modules --- pype/modules/base.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pype/modules/base.py b/pype/modules/base.py index 43ed570e19..525320f1a7 100644 --- a/pype/modules/base.py +++ b/pype/modules/base.py @@ -322,7 +322,13 @@ class ModulesManager: enabled_modules = self.get_enabled_modules() self.log.debug("Has {} enabled modules.".format(len(enabled_modules))) for module in enabled_modules: - module.connect_with_modules(enabled_modules) + try: + module.connect_with_modules(enabled_modules) + except Exception: + self.log.error( + "BUG: Module failed on connection with other modules.", + exc_info=True + ) def get_enabled_modules(self): """Enabled modules initialized by the manager. From 7798f24fa772c65bf1b822fe06f1825aa981a31a Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 17 Dec 2020 10:58:46 +0100 Subject: [PATCH 11/13] better fix of registering paths --- pype/tools/launcher/actions.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/pype/tools/launcher/actions.py b/pype/tools/launcher/actions.py index 5d52b44acd..ad1a2d524b 100644 --- a/pype/tools/launcher/actions.py +++ b/pype/tools/launcher/actions.py @@ -90,6 +90,19 @@ def register_actions_from_paths(paths): return for path in paths: + if not path: + continue + + if path.startswith("."): + print(( + "BUG: Relative paths are not allowed for security reasons. {}" + ).format(path)) + continue + + if not os.path.exists(path): + print("Path was not found: {}".format(path)) + continue + api.register_plugin_path(api.Action, path) # Run "register" if found. @@ -111,12 +124,7 @@ def register_environment_actions(): """Register actions from AVALON_ACTIONS for Launcher.""" paths_str = os.environ.get("AVALON_ACTIONS") or "" - paths = [] - for path in paths_str.split(os.pathsep): - if path and os.path.exists(path): - paths.append(path) - - register_actions_from_paths(paths) + register_actions_from_paths(paths_str.split(os.pathsep)) class ApplicationAction(api.Action): From 0874853f63e25846839cef27a93c4e7ed8d6f797 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 17 Dec 2020 11:09:44 +0100 Subject: [PATCH 12/13] actions do not `Run "register" if found.` --- pype/tools/launcher/actions.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/pype/tools/launcher/actions.py b/pype/tools/launcher/actions.py index ad1a2d524b..aefa190768 100644 --- a/pype/tools/launcher/actions.py +++ b/pype/tools/launcher/actions.py @@ -105,20 +105,6 @@ def register_actions_from_paths(paths): api.register_plugin_path(api.Action, path) - # Run "register" if found. - for module in lib.modules_from_path(path): - if "register" not in dir(module): - continue - - try: - module.register() - except Exception as e: - print( - "Register method in {0} failed: {1}".format( - module, str(e) - ) - ) - def register_environment_actions(): """Register actions from AVALON_ACTIONS for Launcher.""" From 72f6d3b4afa7d88cb05344e2551f2555416440e9 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 17 Dec 2020 11:09:56 +0100 Subject: [PATCH 13/13] module importing has security checks now --- pype/lib/python_module_tools.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pype/lib/python_module_tools.py b/pype/lib/python_module_tools.py index 2ce2f60dca..b5400c9981 100644 --- a/pype/lib/python_module_tools.py +++ b/pype/lib/python_module_tools.py @@ -18,10 +18,20 @@ def modules_from_path(folder_path): Returns: List of modules. """ + modules = [] + # Just skip and return empty list if path is not set + if not folder_path: + return modules + + # Do not allow relative imports + if folder_path.startswith("."): + log.warning(( + "BUG: Relative paths are not allowed for security reasons. {}" + ).format(folder_path)) + return modules folder_path = os.path.normpath(folder_path) - modules = [] if not os.path.isdir(folder_path): log.warning("Not a directory path: {}".format(folder_path)) return modules