From f8e594be800010b4e535de9e051a93982365f369 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 9 Nov 2021 16:55:11 +0100 Subject: [PATCH 01/10] added module command --- openpype/cli.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/openpype/cli.py b/openpype/cli.py index 512bd4663bb..e1f9265c1fc 100644 --- a/openpype/cli.py +++ b/openpype/cli.py @@ -57,6 +57,12 @@ def tray(debug=False): PypeCommands().launch_tray(debug) +@main.group(help="Run command line arguments of OpenPype modules") +@click.pass_context +def module(ctx): + pass + + @main.command() @click.option("-d", "--debug", is_flag=True, help="Print debug messages") @click.option("--ftrack-url", envvar="FTRACK_SERVER", From dee8156a0c2263ac4d75fba9a957ebfd582dff14 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 9 Nov 2021 16:56:17 +0100 Subject: [PATCH 02/10] implemented 'add_modules' which will call cli method on module to give ability to register custom cli commands --- openpype/cli.py | 1 + openpype/pype_commands.py | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/openpype/cli.py b/openpype/cli.py index e1f9265c1fc..d68cba45c6e 100644 --- a/openpype/cli.py +++ b/openpype/cli.py @@ -57,6 +57,7 @@ def tray(debug=False): PypeCommands().launch_tray(debug) +@PypeCommands.add_modules @main.group(help="Run command line arguments of OpenPype modules") @click.pass_context def module(ctx): diff --git a/openpype/pype_commands.py b/openpype/pype_commands.py index 5fac5cacc74..f4a29091d02 100644 --- a/openpype/pype_commands.py +++ b/openpype/pype_commands.py @@ -41,6 +41,17 @@ def launch_settings_gui(dev): user_role = "manager" settings.main(user_role) + @staticmethod + def add_modules(click_func): + """Modules/Addons can add their cli commands dynamically.""" + from openpype.modules import ModulesManager + + manager = ModulesManager() + for module in manager.modules: + if hasattr(module, "cli"): + module.cli(click_func) + return click_func + @staticmethod def launch_eventservercli(*args): from openpype_modules.ftrack.ftrack_server.event_server_cli import ( From afd93a403567f9d79bf4569b8b98419993186c6d Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 9 Nov 2021 16:57:02 +0100 Subject: [PATCH 03/10] ftrack uses new cli option to register it's cli commands --- .../default_modules/ftrack/ftrack_module.py | 58 ++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/openpype/modules/default_modules/ftrack/ftrack_module.py b/openpype/modules/default_modules/ftrack/ftrack_module.py index 73a4dfee822..cc9210c2162 100644 --- a/openpype/modules/default_modules/ftrack/ftrack_module.py +++ b/openpype/modules/default_modules/ftrack/ftrack_module.py @@ -1,8 +1,10 @@ import os import json import collections -from openpype.modules import OpenPypeModule +import click + +from openpype.modules import OpenPypeModule from openpype_interfaces import ( ITrayModule, IPluginPaths, @@ -409,3 +411,57 @@ def get_task_time(self, project_name, asset_name, task_name): return 0 hours_logged = (task_entity["time_logged"] / 60) / 60 return hours_logged + + def cli(self, click_group): + click_group.add_command(cli_main) + + +@click.group( + FtrackModule.name, + help="Application job server. Can be used as render farm." +) +def cli_main(): + pass + + +@cli_main.command() +@click.option("-d", "--debug", is_flag=True, help="Print debug messages") +@click.option("--ftrack-url", envvar="FTRACK_SERVER", + help="Ftrack server url") +@click.option("--ftrack-user", envvar="FTRACK_API_USER", + help="Ftrack api user") +@click.option("--ftrack-api-key", envvar="FTRACK_API_KEY", + help="Ftrack api key") +@click.option("--legacy", is_flag=True, + help="run event server without mongo storing") +@click.option("--clockify-api-key", envvar="CLOCKIFY_API_KEY", + help="Clockify API key.") +@click.option("--clockify-workspace", envvar="CLOCKIFY_WORKSPACE", + help="Clockify workspace") +def eventserver( + debug, + ftrack_url, + ftrack_user, + ftrack_api_key, + legacy, + clockify_api_key, + clockify_workspace +): + """Launch ftrack event server. + + This should be ideally used by system service (such us systemd or upstart + on linux and window service). + """ + if debug: + os.environ["OPENPYPE_DEBUG"] = "3" + + from .ftrack_server.event_server_cli import run_event_server + + return run_event_server( + ftrack_url, + ftrack_user, + ftrack_api_key, + legacy, + clockify_api_key, + clockify_workspace + ) From 88ac91c82c79f036108ccd37cb95103243588ce6 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 9 Nov 2021 17:50:44 +0100 Subject: [PATCH 04/10] fix help --- openpype/modules/default_modules/ftrack/ftrack_module.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/openpype/modules/default_modules/ftrack/ftrack_module.py b/openpype/modules/default_modules/ftrack/ftrack_module.py index cc9210c2162..6db80e6c4a3 100644 --- a/openpype/modules/default_modules/ftrack/ftrack_module.py +++ b/openpype/modules/default_modules/ftrack/ftrack_module.py @@ -416,10 +416,7 @@ def cli(self, click_group): click_group.add_command(cli_main) -@click.group( - FtrackModule.name, - help="Application job server. Can be used as render farm." -) +@click.group(FtrackModule.name, help="Ftrack module related commands.") def cli_main(): pass From 2f4ee4447e0d24b1213dc6290ea16af3e27e9531 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 9 Nov 2021 17:51:45 +0100 Subject: [PATCH 05/10] example addon has cli commands --- .../example_addons/example_addon/addon.py | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/openpype/modules/example_addons/example_addon/addon.py b/openpype/modules/example_addons/example_addon/addon.py index 5573e33cc15..f4a1aa4f4e7 100644 --- a/openpype/modules/example_addons/example_addon/addon.py +++ b/openpype/modules/example_addons/example_addon/addon.py @@ -8,10 +8,12 @@ """ import os +import click from openpype.modules import ( JsonFilesSettingsDef, - OpenPypeAddOn + OpenPypeAddOn, + ModulesManager ) # Import interface defined by this addon to be able find other addons using it from openpype_interfaces import ( @@ -130,3 +132,32 @@ def get_plugin_paths(self): return { "publish": [os.path.join(current_dir, "plugins", "publish")] } + + def cli(self, click_group): + click_group.add_command(cli_main) + + +@click.group(ExampleAddon.name, help="Example addon dynamic cli commands.") +def cli_main(): + pass + + +@cli_main.command() +def nothing(): + """Does nothing but print a message.""" + print("You've triggered \"nothing\" command.") + + +@cli_main.command() +def show_dialog(): + """Show ExampleAddon dialog. + + We don't have access to addon directly through cli so we have to create + it again. + """ + from openpype.tools.utils.lib import qt_app_context + + manager = ModulesManager() + example_addon = manager.modules_by_name[ExampleAddon.name] + with qt_app_context(): + example_addon.show_dialog() From bf9d4442ea904004ce080a550a5ea1b5aa476d93 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 9 Nov 2021 17:55:31 +0100 Subject: [PATCH 06/10] added cli info to modules readme --- openpype/modules/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openpype/modules/README.md b/openpype/modules/README.md index 57163243651..7c170254870 100644 --- a/openpype/modules/README.md +++ b/openpype/modules/README.md @@ -22,6 +22,10 @@ OpenPype modules should contain separated logic of specific kind of implementati - `__init__` should not be overridden 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 +- `cli` method - can add cli commands specific for the module + - command line arguments are handled using `click` python module + - `cli` method should expect single argument which is click group on which can be called any group specific methods (e.g. `add_command` to add another click group as children see `ExampleAddon`) + - it is possible to add trigger cli commands using `./openpype_console module *args` ## Addon class `OpenPypeAddOn` - inherits from `OpenPypeModule` but is enabled by default and doesn't have to implement `initialize` and `connect_with_modules` methods @@ -140,4 +144,4 @@ class ClockifyModule( ### TrayModulesManager - inherits from `ModulesManager` -- has specific implementation for Pype Tray tool and handle `ITrayModule` methods \ No newline at end of file +- has specific implementation for Pype Tray tool and handle `ITrayModule` methods From 887e4ba004446392f89b605727d6f7447b1b5452 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 9 Nov 2021 17:55:51 +0100 Subject: [PATCH 07/10] do not crash of failed calling of 'cli' method --- openpype/pype_commands.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/openpype/pype_commands.py b/openpype/pype_commands.py index f4a29091d02..d4cba6f93e9 100644 --- a/openpype/pype_commands.py +++ b/openpype/pype_commands.py @@ -47,9 +47,18 @@ def add_modules(click_func): from openpype.modules import ModulesManager manager = ModulesManager() + log = PypeLogger.get_logger("AddModulesCLI") for module in manager.modules: if hasattr(module, "cli"): - module.cli(click_func) + try: + module.cli(click_func) + + except Exception: + log.warning( + "Failed to add cli command for module \"{}\"".format( + module.name + ) + ) return click_func @staticmethod From 901eb5bc9dbd850a32c43d3e4f4ea0acfabb5aa3 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 9 Nov 2021 18:02:19 +0100 Subject: [PATCH 08/10] added cli method to default methods of openpypemodule --- openpype/modules/README.md | 2 +- openpype/modules/base.py | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/openpype/modules/README.md b/openpype/modules/README.md index 7c170254870..86afdb9d91f 100644 --- a/openpype/modules/README.md +++ b/openpype/modules/README.md @@ -22,7 +22,7 @@ OpenPype modules should contain separated logic of specific kind of implementati - `__init__` should not be overridden 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 -- `cli` method - can add cli commands specific for the module +- `cli` method - add cli commands specific for the module - command line arguments are handled using `click` python module - `cli` method should expect single argument which is click group on which can be called any group specific methods (e.g. `add_command` to add another click group as children see `ExampleAddon`) - it is possible to add trigger cli commands using `./openpype_console module *args` diff --git a/openpype/modules/base.py b/openpype/modules/base.py index 7779fff6ec0..5773c684b69 100644 --- a/openpype/modules/base.py +++ b/openpype/modules/base.py @@ -431,6 +431,28 @@ def get_global_environments(self): """ return {} + def cli(self, module_click_group): + """Add commands to click group. + + The best practise is to create click group for whole module which is + used to separate commands. + + class MyPlugin(OpenPypeModule): + ... + def cli(self, module_click_group): + module_click_group.add_command(cli_main) + + + @click.group(, help="") + def cli_main(): + pass + + @cli_main.command() + def mycommand(): + print("my_command") + """ + pass + class OpenPypeAddOn(OpenPypeModule): # Enable Addon by default From 2709ece76ad9823921b668427b647958131a2110 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 9 Nov 2021 18:08:30 +0100 Subject: [PATCH 09/10] check of cli existence is not needed anymore --- openpype/pype_commands.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/openpype/pype_commands.py b/openpype/pype_commands.py index d4cba6f93e9..5ff57ab6ad6 100644 --- a/openpype/pype_commands.py +++ b/openpype/pype_commands.py @@ -49,16 +49,15 @@ def add_modules(click_func): manager = ModulesManager() log = PypeLogger.get_logger("AddModulesCLI") for module in manager.modules: - if hasattr(module, "cli"): - try: - module.cli(click_func) - - except Exception: - log.warning( - "Failed to add cli command for module \"{}\"".format( - module.name - ) + try: + module.cli(click_func) + + except Exception: + log.warning( + "Failed to add cli command for module \"{}\"".format( + module.name ) + ) return click_func @staticmethod From 5acdb6e182efede7d01d136c431c41329e77e203 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 11 Nov 2021 14:53:57 +0100 Subject: [PATCH 10/10] added docstring --- openpype/cli.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openpype/cli.py b/openpype/cli.py index d68cba45c6e..6a4d8f11206 100644 --- a/openpype/cli.py +++ b/openpype/cli.py @@ -61,6 +61,10 @@ def tray(debug=False): @main.group(help="Run command line arguments of OpenPype modules") @click.pass_context def module(ctx): + """Module specific commands created dynamically. + + These commands are generated dynamically by currently loaded addon/modules. + """ pass