Skip to content

Launcher tool: Use webactions #1226

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 54 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
172fc27
remove applications action logic
iLLiCiTiT Apr 3, 2025
05ba75c
added more options how to icon can be defined
iLLiCiTiT Apr 3, 2025
9123994
added baseic way to show webactions
iLLiCiTiT Apr 3, 2025
698fef2
added helper function to get settings variant
iLLiCiTiT Apr 4, 2025
9a81643
added addon name and version to action data
iLLiCiTiT Apr 4, 2025
d07e3b9
implemented webaction trigger
iLLiCiTiT Apr 4, 2025
777b835
added 'transparent' icon type
iLLiCiTiT Apr 4, 2025
3917038
handle empty icon in actions widget
iLLiCiTiT Apr 4, 2025
4d1ad75
handle missing icon in action manifest
iLLiCiTiT Apr 4, 2025
4cf0c9b
Merge branch 'develop' into feature/107-webactions-in-launcher-tool
iLLiCiTiT Apr 7, 2025
c97b58f
fix boolean comparison
iLLiCiTiT Apr 7, 2025
c214aa5
Merge branch 'develop' into feature/107-webactions-in-launcher-tool
iLLiCiTiT Apr 15, 2025
1a0e099
added config fields into actions model
iLLiCiTiT Apr 15, 2025
4d69784
added new methods to controller
iLLiCiTiT Apr 15, 2025
99a7d2f
implemented base of action config UI
iLLiCiTiT Apr 15, 2025
6dcd8f2
implemented helper method to set values of dialog
iLLiCiTiT Apr 15, 2025
63408d7
use current values for UI
iLLiCiTiT Apr 15, 2025
79b09e6
move types to docstring
iLLiCiTiT Apr 15, 2025
95bf292
fix spacing
iLLiCiTiT Apr 16, 2025
4e9a2a5
Merge branch 'develop' into feature/107-webactions-in-launcher-tool
iLLiCiTiT Apr 16, 2025
ce13754
set 'referer' header
iLLiCiTiT Apr 16, 2025
867dae4
pass action label to trigger action
iLLiCiTiT Apr 22, 2025
f670029
added option to run detached process
iLLiCiTiT Apr 22, 2025
d84f33b
use run detached ayon launcher process to run webactions
iLLiCiTiT Apr 22, 2025
5e84153
Merge branch 'develop' into feature/107-webactions-in-launcher-tool
iLLiCiTiT Apr 22, 2025
9e21c4d
handle missing 'color'
iLLiCiTiT Apr 22, 2025
31803b0
don't fail whole UI if icon cannot be parsed
iLLiCiTiT Apr 22, 2025
f2390a7
use correct color value
iLLiCiTiT Apr 22, 2025
6440974
raise error when running server action
iLLiCiTiT Apr 22, 2025
4b385c1
change place where missing key is handled
iLLiCiTiT Apr 22, 2025
33df9ec
fox example
iLLiCiTiT Apr 22, 2025
2513741
Merge branch 'develop' into feature/107-webactions-in-launcher-tool
iLLiCiTiT Apr 29, 2025
a93c877
Merge branch 'develop' into feature/107-webactions-in-launcher-tool
iLLiCiTiT May 7, 2025
34d66c6
split trigger or action and webaction
iLLiCiTiT May 7, 2025
8338680
basic implementation of webactions handling
iLLiCiTiT May 7, 2025
c7526b5
revert dialog conditions
iLLiCiTiT May 7, 2025
acd5916
better download uri handling
iLLiCiTiT May 7, 2025
4728258
download image from url
iLLiCiTiT May 7, 2025
34dcc78
added more options to attribute definitions dialog
iLLiCiTiT May 7, 2025
149c904
added markdown label
iLLiCiTiT May 7, 2025
c29d14d
use markdown label for attribute definitions label
iLLiCiTiT May 7, 2025
27dc51a
enhance actions utils in loader
iLLiCiTiT May 7, 2025
1a7b137
better detection of ayon url
iLLiCiTiT May 7, 2025
bb168a1
actually fill form correctly
iLLiCiTiT May 7, 2025
0fc29ae
show form correctly
iLLiCiTiT May 7, 2025
cd63538
fix variable name
iLLiCiTiT May 7, 2025
d7d3d1b
log traceback
iLLiCiTiT May 7, 2025
6bcf514
add TypeError to avoid typehint issues
iLLiCiTiT May 7, 2025
839eecc
remove unused variable
iLLiCiTiT May 7, 2025
0cbdda1
store the values into variables
iLLiCiTiT May 7, 2025
d5063e0
convert default values to correct type
iLLiCiTiT May 7, 2025
131b4fb
safe key access
iLLiCiTiT May 9, 2025
5f18f63
formatting fix
iLLiCiTiT May 9, 2025
73a45f5
more config fields conversion fixes
iLLiCiTiT May 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions client/ayon_core/lib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
run_subprocess,
run_detached_process,
run_ayon_launcher_process,
run_detached_ayon_launcher_process,
path_to_subprocess_arg,
CREATE_NO_WINDOW
)
Expand Down Expand Up @@ -131,6 +132,7 @@
is_staging_enabled,
is_dev_mode_enabled,
is_in_tests,
get_settings_variant,
)

terminal = Terminal
Expand Down Expand Up @@ -160,6 +162,7 @@
"run_subprocess",
"run_detached_process",
"run_ayon_launcher_process",
"run_detached_ayon_launcher_process",
"path_to_subprocess_arg",
"CREATE_NO_WINDOW",

Expand Down Expand Up @@ -240,4 +243,5 @@
"is_staging_enabled",
"is_dev_mode_enabled",
"is_in_tests",
"get_settings_variant",
]
24 changes: 20 additions & 4 deletions client/ayon_core/lib/ayon_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,15 @@ def is_using_ayon_console():
return "ayon_console" in executable_filename


def is_headless_mode_enabled():
def is_headless_mode_enabled() -> bool:
return os.getenv("AYON_HEADLESS_MODE") == "1"


def is_staging_enabled():
def is_staging_enabled() -> bool:
return os.getenv("AYON_USE_STAGING") == "1"


def is_in_tests():
def is_in_tests() -> bool:
"""Process is running in automatic tests mode.

Returns:
Expand All @@ -96,7 +96,7 @@ def is_in_tests():
return os.environ.get("AYON_IN_TESTS") == "1"


def is_dev_mode_enabled():
def is_dev_mode_enabled() -> bool:
"""Dev mode is enabled in AYON.

Returns:
Expand All @@ -106,6 +106,22 @@ def is_dev_mode_enabled():
return os.getenv("AYON_USE_DEV") == "1"


def get_settings_variant() -> str:
"""Get AYON settings variant.

Returns:
str: Settings variant.

"""
if is_dev_mode_enabled():
return os.environ["AYON_BUNDLE_NAME"]

if is_staging_enabled():
return "staging"

return "production"


def get_ayon_info():
executable_args = get_ayon_launcher_args()
if is_running_from_build():
Expand Down
87 changes: 62 additions & 25 deletions client/ayon_core/lib/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,29 +201,7 @@ def clean_envs_for_ayon_process(env=None):
return env


def run_ayon_launcher_process(*args, add_sys_paths=False, **kwargs):
"""Execute AYON process with passed arguments and wait.

Wrapper for 'run_process' which prepends AYON executable arguments
before passed arguments and define environments if are not passed.

Values from 'os.environ' are used for environments if are not passed.
They are cleaned using 'clean_envs_for_ayon_process' function.

Example:
```
run_ayon_process("run", "<path to .py script>")
```

Args:
*args (str): ayon-launcher cli arguments.
**kwargs (Any): Keyword arguments for subprocess.Popen.

Returns:
str: Full output of subprocess concatenated stdout and stderr.

"""
args = get_ayon_launcher_args(*args)
def _prepare_ayon_launcher_env(add_sys_paths: bool, kwargs):
env = kwargs.pop("env", None)
# Keep env untouched if are passed and not empty
if not env:
Expand All @@ -239,8 +217,7 @@ def run_ayon_launcher_process(*args, add_sys_paths=False, **kwargs):
new_pythonpath.append(path)
lookup_set.add(path)
env["PYTHONPATH"] = os.pathsep.join(new_pythonpath)

return run_subprocess(args, env=env, **kwargs)
return env


def run_detached_process(args, **kwargs):
Expand Down Expand Up @@ -314,6 +291,66 @@ def run_detached_process(args, **kwargs):
return process


def run_ayon_launcher_process(
*args, add_sys_paths=False, **kwargs
):
"""Execute AYON process with passed arguments and wait.

Wrapper for 'run_process' which prepends AYON executable arguments
before passed arguments and define environments if are not passed.

Values from 'os.environ' are used for environments if are not passed.
They are cleaned using 'clean_envs_for_ayon_process' function.

Example:
```
run_ayon_launcher_process("run", "<path to .py script>")
```

Args:
*args (str): ayon-launcher cli arguments.
add_sys_paths (bool): Add system paths to PYTHONPATH.
**kwargs (Any): Keyword arguments for subprocess.Popen.

Returns:
str: Full output of subprocess concatenated stdout and stderr.

"""
args = get_ayon_launcher_args(*args)
env = _prepare_ayon_launcher_env(add_sys_paths, kwargs)
return run_subprocess(args, env=env, **kwargs)


def run_detached_ayon_launcher_process(
*args, add_sys_paths=False, **kwargs
):
"""Execute AYON process with passed arguments and wait.

Wrapper for 'run_process' which prepends AYON executable arguments
before passed arguments and define environments if are not passed.

Values from 'os.environ' are used for environments if are not passed.
They are cleaned using 'clean_envs_for_ayon_process' function.

Example:
```
run_detached_ayon_launcher_process("run", "<path to .py script>")
```

Args:
*args (str): ayon-launcher cli arguments.
add_sys_paths (bool): Add system paths to PYTHONPATH.
**kwargs (Any): Keyword arguments for subprocess.Popen.

Returns:
str: Full output of subprocess concatenated stdout and stderr.

"""
args = get_ayon_launcher_args(*args)
env = _prepare_ayon_launcher_env(add_sys_paths, kwargs)
return run_detached_process(args, env=env, **kwargs)


def path_to_subprocess_arg(path):
"""Prepare path for subprocess arguments.

Expand Down
9 changes: 2 additions & 7 deletions client/ayon_core/settings/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,9 @@ def _use_bundles(cls):
@classmethod
def _get_variant(cls):
if _AyonSettingsCache.variant is None:
from ayon_core.lib import is_staging_enabled, is_dev_mode_enabled

variant = "production"
if is_dev_mode_enabled():
variant = cls._get_bundle_name()
elif is_staging_enabled():
variant = "staging"
from ayon_core.lib import get_settings_variant

variant = get_settings_variant()
# Cache variant
_AyonSettingsCache.variant = variant

Expand Down
73 changes: 66 additions & 7 deletions client/ayon_core/tools/attribute_defs/dialog.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,92 @@
from qtpy import QtWidgets
from __future__ import annotations

from typing import Optional

from qtpy import QtWidgets, QtGui

from ayon_core.style import load_stylesheet
from ayon_core.resources import get_ayon_icon_filepath
from ayon_core.lib import AbstractAttrDef

from .widgets import AttributeDefinitionsWidget


class AttributeDefinitionsDialog(QtWidgets.QDialog):
def __init__(self, attr_defs, parent=None):
super(AttributeDefinitionsDialog, self).__init__(parent)
def __init__(
self,
attr_defs: list[AbstractAttrDef],
title: Optional[str] = None,
submit_label: Optional[str] = None,
cancel_label: Optional[str] = None,
submit_icon: Optional[QtGui.QIcon] = None,
cancel_icon: Optional[QtGui.QIcon] = None,
parent: Optional[QtWidgets.QWidget] = None,
):
super().__init__(parent)

if title:
self.setWindowTitle(title)

icon = QtGui.QIcon(get_ayon_icon_filepath())
self.setWindowIcon(icon)
self.setStyleSheet(load_stylesheet())

attrs_widget = AttributeDefinitionsWidget(attr_defs, self)

if submit_label is None:
submit_label = "OK"

if cancel_label is None:
cancel_label = "Cancel"

btns_widget = QtWidgets.QWidget(self)
ok_btn = QtWidgets.QPushButton("OK", btns_widget)
cancel_btn = QtWidgets.QPushButton("Cancel", btns_widget)
cancel_btn = QtWidgets.QPushButton(cancel_label, btns_widget)
submit_btn = QtWidgets.QPushButton(submit_label, btns_widget)

if submit_icon is not None:
submit_btn.setIcon(submit_icon)

if cancel_icon is not None:
cancel_btn.setIcon(cancel_icon)

btns_layout = QtWidgets.QHBoxLayout(btns_widget)
btns_layout.setContentsMargins(0, 0, 0, 0)
btns_layout.addStretch(1)
btns_layout.addWidget(ok_btn, 0)
btns_layout.addWidget(submit_btn, 0)
btns_layout.addWidget(cancel_btn, 0)

main_layout = QtWidgets.QVBoxLayout(self)
main_layout.addWidget(attrs_widget, 0)
main_layout.addStretch(1)
main_layout.addWidget(btns_widget, 0)

ok_btn.clicked.connect(self.accept)
submit_btn.clicked.connect(self.accept)
cancel_btn.clicked.connect(self.reject)

self._attrs_widget = attrs_widget
self._submit_btn = submit_btn
self._cancel_btn = cancel_btn

def get_values(self):
return self._attrs_widget.current_value()

def set_values(self, values):
self._attrs_widget.set_value(values)

def set_submit_label(self, text: str):
self._submit_btn.setText(text)

def set_submit_icon(self, icon: QtGui.QIcon):
self._submit_btn.setIcon(icon)

def set_submit_visible(self, visible: bool):
self._submit_btn.setVisible(visible)

def set_cancel_label(self, text: str):
self._cancel_btn.setText(text)

def set_cancel_icon(self, icon: QtGui.QIcon):
self._cancel_btn.setIcon(icon)

def set_cancel_visible(self, visible: bool):
self._cancel_btn.setVisible(visible)
5 changes: 2 additions & 3 deletions client/ayon_core/tools/attribute_defs/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
FocusSpinBox,
FocusDoubleSpinBox,
MultiSelectionComboBox,
MarkdownLabel,
PlaceholderLineEdit,
PlaceholderPlainTextEdit,
set_style_property,
Expand Down Expand Up @@ -247,12 +248,10 @@ def add_attr_defs(self, attr_defs):

def set_value(self, value):
new_value = copy.deepcopy(value)
unused_keys = set(new_value.keys())
for widget in self._widgets_by_id.values():
attr_def = widget.attr_def
if attr_def.key not in new_value:
continue
unused_keys.remove(attr_def.key)

widget_value = new_value[attr_def.key]
if widget_value is None:
Expand Down Expand Up @@ -350,7 +349,7 @@ def _ui_init(self):

class LabelAttrWidget(_BaseAttrDefWidget):
def _ui_init(self):
input_widget = QtWidgets.QLabel(self)
input_widget = MarkdownLabel(self)
label = self.attr_def.label
if label:
input_widget.setText(str(label))
Expand Down
Loading
Loading