Merge branch 'develop' into feature/AY-5998_DL-Search--replace-in-environment-values-requires-a-Value

This commit is contained in:
Jakub Trllo 2024-07-25 15:02:00 +02:00 committed by GitHub
commit 7c143ee433
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 97 additions and 28 deletions

View file

@ -43,7 +43,8 @@ class AliasedGroup(click.Group):
help="Enable debug")
@click.option("--verbose", expose_value=False,
help=("Change AYON log level (debug - critical or 0-50)"))
def main_cli(ctx):
@click.option("--force", is_flag=True, hidden=True)
def main_cli(ctx, force):
"""AYON is main command serving as entry point to pipeline system.
It wraps different commands together.
@ -55,17 +56,24 @@ def main_cli(ctx):
print(ctx.get_help())
sys.exit(0)
else:
ctx.invoke(tray)
ctx.forward(tray)
@main_cli.command()
def tray():
@click.option(
"--force",
is_flag=True,
help="Force to start tray and close any existing one.")
def tray(force):
"""Launch AYON tray.
Default action of AYON command is to launch tray widget to control basic
aspects of AYON. See documentation for more information.
"""
Commands.launch_tray()
from ayon_core.tools.tray import main
main(force)
@main_cli.group(help="Run command line arguments of AYON addons")

View file

@ -13,12 +13,6 @@ class Commands:
Most of its methods are called by :mod:`cli` module.
"""
@staticmethod
def launch_tray():
from ayon_core.tools.tray import main
main()
@staticmethod
def publish(
path: str,

View file

@ -8,7 +8,7 @@ from datetime import datetime
import websocket
from ayon_core.lib import Logger
from ayon_core.tools.tray.webserver import HostMsgAction
from ayon_core.tools.tray import HostMsgAction
log = Logger.get_logger(__name__)

View file

@ -1,21 +1,21 @@
from .webserver import HostMsgAction
from .addons_manager import TrayAddonsManager
from .structures import HostMsgAction
from .lib import (
TrayState,
get_tray_state,
is_tray_running,
get_tray_server_url,
make_sure_tray_is_running,
main,
)
__all__ = (
"HostMsgAction",
"TrayAddonsManager",
"TrayState",
"get_tray_state",
"is_tray_running",
"get_tray_server_url",
"make_sure_tray_is_running",
"main",
)

View file

@ -7,12 +7,13 @@ import subprocess
import csv
import time
import signal
import locale
from typing import Optional, Dict, Tuple, Any
import ayon_api
import requests
from ayon_core.lib import Logger
from ayon_core.lib import Logger, get_ayon_launcher_args, run_detached_process
from ayon_core.lib.local_settings import get_ayon_appdirs
@ -50,7 +51,8 @@ def _get_server_and_variant(
def _windows_pid_is_running(pid: int) -> bool:
args = ["tasklist.exe", "/fo", "csv", "/fi", f"PID eq {pid}"]
output = subprocess.check_output(args)
csv_content = csv.DictReader(output.decode("utf-8").splitlines())
encoding = locale.getpreferredencoding()
csv_content = csv.DictReader(output.decode(encoding).splitlines())
# if "PID" not in csv_content.fieldnames:
# return False
for _ in csv_content:
@ -122,6 +124,11 @@ def _wait_for_starting_tray(
if data.get("started") is True:
return data
pid = data.get("pid")
if pid and not _is_process_running(pid):
remove_tray_server_url()
return None
if time.time() - started_at > timeout:
return None
time.sleep(0.1)
@ -274,7 +281,12 @@ def remove_tray_server_url(force: Optional[bool] = False):
except BaseException:
data = {}
if force or not data or data.get("pid") == os.getpid():
if (
force
or not data
or data.get("pid") == os.getpid()
or not _is_process_running(data.get("pid"))
):
os.remove(filepath)
@ -344,12 +356,61 @@ def is_tray_running(
return state != TrayState.NOT_RUNNING
def main():
def make_sure_tray_is_running(
ayon_url: Optional[str] = None,
variant: Optional[str] = None,
env: Optional[Dict[str, str]] = None
):
"""Make sure that tray for AYON url and variant is running.
Args:
ayon_url (Optional[str]): AYON server url.
variant (Optional[str]): Settings variant.
env (Optional[Dict[str, str]]): Environment variables for the process.
"""
state = get_tray_state(ayon_url, variant)
if state == TrayState.RUNNING:
return
if state == TrayState.STARTING:
_wait_for_starting_tray(ayon_url, variant)
state = get_tray_state(ayon_url, variant)
if state == TrayState.RUNNING:
return
args = get_ayon_launcher_args("tray", "--force")
if env is None:
env = os.environ.copy()
# Make sure 'QT_API' is not set
env.pop("QT_API", None)
if ayon_url:
env["AYON_SERVER_URL"] = ayon_url
# TODO maybe handle variant in a better way
if variant:
if variant == "staging":
args.append("--use-staging")
run_detached_process(args, env=env)
def main(force=False):
from ayon_core.tools.tray.ui import main
Logger.set_process_name("Tray")
state = get_tray_state()
if force and state in (TrayState.RUNNING, TrayState.STARTING):
file_info = get_tray_file_info() or {}
pid = file_info.get("pid")
if pid is not None:
_kill_tray_process(pid)
remove_tray_server_url(force=True)
state = TrayState.NOT_RUNNING
if state == TrayState.RUNNING:
print("Tray is already running.")
return

View file

@ -3,12 +3,11 @@ import sys
import time
import collections
import atexit
import json
import platform
from aiohttp.web_response import Response
import ayon_api
from qtpy import QtCore, QtGui, QtWidgets
from aiohttp.web import Response, json_response, Request
from ayon_core import resources, style
from ayon_core.lib import (
@ -28,13 +27,13 @@ from ayon_core.tools.utils import (
WrappedCallbackItem,
get_ayon_qt_app,
)
from ayon_core.tools.tray import TrayAddonsManager
from ayon_core.tools.tray.lib import (
set_tray_server_url,
remove_tray_server_url,
TrayIsRunningError,
)
from .addons_manager import TrayAddonsManager
from .host_console_listener import HostListener
from .info_widget import InfoWidget
from .dialogs import (
@ -91,6 +90,10 @@ class TrayManager:
self._services_submenu = None
self._start_time = time.time()
# Cache AYON username used in process
# - it can change only by changing ayon_api global connection
# should be safe for tray application to cache the value only once
self._cached_username = None
self._closing = False
try:
set_tray_server_url(
@ -143,7 +146,7 @@ class TrayManager:
self._addons_manager.initialize(tray_menu)
self._addons_manager.add_route(
"GET", "/tray", self._get_web_tray_info
"GET", "/tray", self._web_get_tray_info
)
admin_submenu = ITrayAction.admin_submenu(tray_menu)
@ -274,8 +277,12 @@ class TrayManager:
return item
async def _get_web_tray_info(self, request):
return Response(text=json.dumps({
async def _web_get_tray_info(self, _request: Request) -> Response:
if self._cached_username is None:
self._cached_username = ayon_api.get_user()["name"]
return json_response({
"username": self._cached_username,
"bundle": os.getenv("AYON_BUNDLE_NAME"),
"dev_mode": is_dev_mode_enabled(),
"staging_mode": is_staging_enabled(),
@ -285,7 +292,7 @@ class TrayManager:
},
"installer_version": os.getenv("AYON_VERSION"),
"running_time": time.time() - self._start_time,
}))
})
def _on_update_check_timer(self):
try:

View file

@ -1,10 +1,8 @@
from .structures import HostMsgAction
from .base_routes import RestApiEndpoint
from .server import find_free_port, WebServerManager
__all__ = (
"HostMsgAction",
"RestApiEndpoint",
"find_free_port",
"WebServerManager",

View file

@ -964,7 +964,8 @@ DEFAULT_PUBLISH_VALUES = {
"nuke",
"harmony",
"photoshop",
"aftereffects"
"aftereffects",
"fusion"
],
"enabled": True,
"optional": True,