Skip to content
This repository has been archived by the owner on Sep 20, 2024. It is now read-only.

Modules: Module can add cli commands #2224

Merged
merged 10 commits into from
Nov 12, 2021
11 changes: 11 additions & 0 deletions openpype/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,17 @@ 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):
"""Module specific commands created dynamically.

These commands are generated dynamically by currently loaded addon/modules.
"""
pass


@main.command()
@click.option("-d", "--debug", is_flag=True, help="Print debug messages")
@click.option("--ftrack-url", envvar="FTRACK_SERVER",
Expand Down
6 changes: 5 additions & 1 deletion openpype/modules/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 - 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 <module_name> <command> *args`

## Addon class `OpenPypeAddOn`
- inherits from `OpenPypeModule` but is enabled by default and doesn't have to implement `initialize` and `connect_with_modules` methods
Expand Down Expand Up @@ -140,4 +144,4 @@ class ClockifyModule(

### TrayModulesManager
- inherits from `ModulesManager`
- has specific implementation for Pype Tray tool and handle `ITrayModule` methods
- has specific implementation for Pype Tray tool and handle `ITrayModule` methods
22 changes: 22 additions & 0 deletions openpype/modules/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(<module name>, help="<Any help shown in cmd>")
def cli_main():
pass

@cli_main.command()
def mycommand():
print("my_command")
"""
pass


class OpenPypeAddOn(OpenPypeModule):
# Enable Addon by default
Expand Down
55 changes: 54 additions & 1 deletion openpype/modules/default_modules/ftrack/ftrack_module.py
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -409,3 +411,54 @@ 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="Ftrack module related commands.")
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
)
33 changes: 32 additions & 1 deletion openpype/modules/example_addons/example_addon/addon.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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()
19 changes: 19 additions & 0 deletions openpype/pype_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,25 @@ 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()
log = PypeLogger.get_logger("AddModulesCLI")
for module in manager.modules:
try:
module.cli(click_func)

except Exception:
log.warning(
"Failed to add cli command for module \"{}\"".format(
module.name
)
)
return click_func

@staticmethod
def launch_eventservercli(*args):
from openpype_modules.ftrack.ftrack_server.event_server_cli import (
Expand Down