mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
add type hints
This commit is contained in:
parent
7368ddfdfb
commit
1caedb841f
1 changed files with 96 additions and 75 deletions
|
|
@ -1,5 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Base class for AYON addons."""
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import os
|
||||
import sys
|
||||
|
|
@ -11,10 +13,11 @@ import collections
|
|||
import warnings
|
||||
from uuid import uuid4
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Optional
|
||||
from types import ModuleType
|
||||
import typing
|
||||
from typing import Optional, Any, Union
|
||||
|
||||
import ayon_api
|
||||
from semver import VersionInfo
|
||||
|
||||
from ayon_core import AYON_CORE_ROOT
|
||||
from ayon_core.lib import (
|
||||
|
|
@ -30,6 +33,11 @@ from .interfaces import (
|
|||
IHostAddon,
|
||||
)
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
import click
|
||||
|
||||
from ayon_core.host import HostBase
|
||||
|
||||
# Files that will be always ignored on addons import
|
||||
IGNORED_FILENAMES = {
|
||||
"__pycache__",
|
||||
|
|
@ -101,7 +109,7 @@ class _LoadCache:
|
|||
addon_modules = []
|
||||
|
||||
|
||||
def load_addons(force=False):
|
||||
def load_addons(force: bool = False) -> None:
|
||||
"""Load AYON addons as python modules.
|
||||
|
||||
Modules does not load only classes (like in Interfaces) because there must
|
||||
|
|
@ -128,7 +136,7 @@ def load_addons(force=False):
|
|||
time.sleep(0.1)
|
||||
|
||||
|
||||
def _get_ayon_bundle_data():
|
||||
def _get_ayon_bundle_data() -> Optional[dict[str, Any]]:
|
||||
studio_bundle_name = os.environ.get("AYON_STUDIO_BUNDLE_NAME")
|
||||
project_bundle_name = os.getenv("AYON_BUNDLE_NAME")
|
||||
bundles = ayon_api.get_bundles()["bundles"]
|
||||
|
|
@ -158,18 +166,21 @@ def _get_ayon_bundle_data():
|
|||
return project_bundle
|
||||
|
||||
|
||||
def _get_ayon_addons_information(bundle_info):
|
||||
def _get_ayon_addons_information(
|
||||
bundle_info: dict[str, Any]
|
||||
) -> list[dict[str, Any]]:
|
||||
"""Receive information about addons to use from server.
|
||||
|
||||
Todos:
|
||||
Actually ask server for the information.
|
||||
Allow project name as optional argument to be able to query information
|
||||
about used addons for specific project.
|
||||
Wrap versions into an object.
|
||||
|
||||
Returns:
|
||||
List[Dict[str, Any]]: List of addon information to use.
|
||||
"""
|
||||
list[dict[str, Any]]: List of addon information to use.
|
||||
|
||||
"""
|
||||
output = []
|
||||
bundle_addons = bundle_info["addons"]
|
||||
addons = ayon_api.get_addons_info()["addons"]
|
||||
|
|
@ -188,7 +199,7 @@ def _get_ayon_addons_information(bundle_info):
|
|||
return output
|
||||
|
||||
|
||||
def _load_ayon_addons(log):
|
||||
def _load_ayon_addons(log: logging.Logger) -> list[ModuleType]:
|
||||
"""Load AYON addons based on information from server.
|
||||
|
||||
This function should not trigger downloading of any addons but only use
|
||||
|
|
@ -198,6 +209,9 @@ def _load_ayon_addons(log):
|
|||
Args:
|
||||
log (logging.Logger): Logger object.
|
||||
|
||||
Returns:
|
||||
list[ModuleType]: Loaded addon modules.
|
||||
|
||||
"""
|
||||
all_addon_modules = []
|
||||
bundle_info = _get_ayon_bundle_data()
|
||||
|
|
@ -325,20 +339,21 @@ class AYONAddon(ABC):
|
|||
|
||||
Attributes:
|
||||
enabled (bool): Is addon enabled.
|
||||
name (str): Addon name.
|
||||
|
||||
Args:
|
||||
manager (AddonsManager): Manager object who discovered addon.
|
||||
settings (dict[str, Any]): AYON settings.
|
||||
|
||||
"""
|
||||
enabled = True
|
||||
enabled: bool = True
|
||||
_id = None
|
||||
|
||||
# Temporary variable for 'version' property
|
||||
_missing_version_warned = False
|
||||
|
||||
def __init__(self, manager, settings):
|
||||
def __init__(
|
||||
self, manager: AddonsManager, settings: dict[str, Any]
|
||||
) -> None:
|
||||
self.manager = manager
|
||||
|
||||
self.log = Logger.get_logger(self.name)
|
||||
|
|
@ -346,7 +361,7 @@ class AYONAddon(ABC):
|
|||
self.initialize(settings)
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
def id(self) -> str:
|
||||
"""Random id of addon object.
|
||||
|
||||
Returns:
|
||||
|
|
@ -359,7 +374,7 @@ class AYONAddon(ABC):
|
|||
|
||||
@property
|
||||
@abstractmethod
|
||||
def name(self):
|
||||
def name(self) -> str:
|
||||
"""Addon name.
|
||||
|
||||
Returns:
|
||||
|
|
@ -369,7 +384,7 @@ class AYONAddon(ABC):
|
|||
pass
|
||||
|
||||
@property
|
||||
def version(self):
|
||||
def version(self) -> str:
|
||||
"""Addon version.
|
||||
|
||||
Todo:
|
||||
|
|
@ -388,7 +403,7 @@ class AYONAddon(ABC):
|
|||
)
|
||||
return "0.0.0"
|
||||
|
||||
def initialize(self, settings):
|
||||
def initialize(self, settings: dict[str, Any]) -> None:
|
||||
"""Initialization of addon attributes.
|
||||
|
||||
It is not recommended to override __init__ that's why specific method
|
||||
|
|
@ -400,7 +415,7 @@ class AYONAddon(ABC):
|
|||
"""
|
||||
pass
|
||||
|
||||
def connect_with_addons(self, enabled_addons):
|
||||
def connect_with_addons(self, enabled_addons: list[AYONAddon]) -> None:
|
||||
"""Connect with other enabled addons.
|
||||
|
||||
Args:
|
||||
|
|
@ -411,7 +426,7 @@ class AYONAddon(ABC):
|
|||
|
||||
def ensure_is_process_ready(
|
||||
self, process_context: ProcessContext
|
||||
):
|
||||
) -> None:
|
||||
"""Make sure addon is prepared for a process.
|
||||
|
||||
This method is called when some action makes sure that addon has set
|
||||
|
|
@ -432,7 +447,7 @@ class AYONAddon(ABC):
|
|||
"""
|
||||
pass
|
||||
|
||||
def get_global_environments(self):
|
||||
def get_global_environments(self) -> dict[str, str]:
|
||||
"""Get global environments values of addon.
|
||||
|
||||
Environment variables that can be get only from system settings.
|
||||
|
|
@ -443,20 +458,12 @@ class AYONAddon(ABC):
|
|||
"""
|
||||
return {}
|
||||
|
||||
def modify_application_launch_arguments(self, application, env):
|
||||
"""Give option to modify launch environments before application launch.
|
||||
|
||||
Implementation is optional. To change environments modify passed
|
||||
dictionary of environments.
|
||||
|
||||
Args:
|
||||
application (Application): Application that is launched.
|
||||
env (dict[str, str]): Current environment variables.
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
def on_host_install(self, host, host_name, project_name):
|
||||
def on_host_install(
|
||||
self,
|
||||
host: HostBase,
|
||||
host_name: str,
|
||||
project_name: str,
|
||||
) -> None:
|
||||
"""Host was installed which gives option to handle in-host logic.
|
||||
|
||||
It is a good option to register in-host event callbacks which are
|
||||
|
|
@ -467,7 +474,7 @@ class AYONAddon(ABC):
|
|||
to receive from 'host' object.
|
||||
|
||||
Args:
|
||||
host (Union[ModuleType, HostBase]): Access to installed/registered
|
||||
host (HostBase): Access to installed/registered
|
||||
host object.
|
||||
host_name (str): Name of host.
|
||||
project_name (str): Project name which is main part of host
|
||||
|
|
@ -476,7 +483,7 @@ class AYONAddon(ABC):
|
|||
"""
|
||||
pass
|
||||
|
||||
def cli(self, addon_click_group):
|
||||
def cli(self, addon_click_group: click.Group) -> None:
|
||||
"""Add commands to click group.
|
||||
|
||||
The best practise is to create click group for whole addon which is
|
||||
|
|
@ -507,15 +514,21 @@ class AYONAddon(ABC):
|
|||
|
||||
class _AddonReportInfo:
|
||||
def __init__(
|
||||
self, class_name, name, version, report_value_by_label
|
||||
):
|
||||
self,
|
||||
class_name: str,
|
||||
name: str,
|
||||
version: str,
|
||||
report_value_by_label: dict[str, Optional[str]],
|
||||
) -> None:
|
||||
self.class_name = class_name
|
||||
self.name = name
|
||||
self.version = version
|
||||
self.report_value_by_label = report_value_by_label
|
||||
|
||||
@classmethod
|
||||
def from_addon(cls, addon, report):
|
||||
def from_addon(
|
||||
cls, addon: AYONAddon, report: dict[str, dict[str, int]]
|
||||
) -> "_AddonReportInfo":
|
||||
class_name = addon.__class__.__name__
|
||||
report_value_by_label = {
|
||||
label: reported.get(class_name)
|
||||
|
|
@ -542,29 +555,35 @@ class AddonsManager:
|
|||
_report_total_key = "Total"
|
||||
_log = None
|
||||
|
||||
def __init__(self, settings=None, initialize=True):
|
||||
def __init__(
|
||||
self,
|
||||
settings: Optional[dict[str, Any]] = None,
|
||||
initialize: bool = True,
|
||||
) -> None:
|
||||
self._settings = settings
|
||||
|
||||
self._addons = []
|
||||
self._addons_by_id = {}
|
||||
self._addons_by_name = {}
|
||||
self._addons: list[AYONAddon] = []
|
||||
self._addons_by_id: dict[str, AYONAddon] = {}
|
||||
self._addons_by_name: dict[str, AYONAddon] = {}
|
||||
# For report of time consumption
|
||||
self._report = {}
|
||||
self._report: dict[str, dict[str, int]] = {}
|
||||
|
||||
if initialize:
|
||||
self.initialize_addons()
|
||||
self.connect_addons()
|
||||
|
||||
def __getitem__(self, addon_name):
|
||||
def __getitem__(self, addon_name: str) -> AYONAddon:
|
||||
return self._addons_by_name[addon_name]
|
||||
|
||||
@property
|
||||
def log(self):
|
||||
def log(self) -> logging.Logger:
|
||||
if self._log is None:
|
||||
self._log = logging.getLogger(self.__class__.__name__)
|
||||
self._log = Logger.get_logger(self.__class__.__name__)
|
||||
return self._log
|
||||
|
||||
def get(self, addon_name, default=None):
|
||||
def get(
|
||||
self, addon_name: str, default: Optional[Any] = None
|
||||
) -> Union[AYONAddon, Any]:
|
||||
"""Access addon by name.
|
||||
|
||||
Args:
|
||||
|
|
@ -578,18 +597,20 @@ class AddonsManager:
|
|||
return self._addons_by_name.get(addon_name, default)
|
||||
|
||||
@property
|
||||
def addons(self):
|
||||
def addons(self) -> list[AYONAddon]:
|
||||
return list(self._addons)
|
||||
|
||||
@property
|
||||
def addons_by_id(self):
|
||||
def addons_by_id(self) -> dict[str, AYONAddon]:
|
||||
return dict(self._addons_by_id)
|
||||
|
||||
@property
|
||||
def addons_by_name(self):
|
||||
def addons_by_name(self) -> dict[str, AYONAddon]:
|
||||
return dict(self._addons_by_name)
|
||||
|
||||
def get_enabled_addon(self, addon_name, default=None):
|
||||
def get_enabled_addon(
|
||||
self, addon_name: str, default: Optional[Any] = None
|
||||
) -> Union[AYONAddon, Any]:
|
||||
"""Fast access to enabled addon.
|
||||
|
||||
If addon is available but is not enabled default value is returned.
|
||||
|
|
@ -600,7 +621,7 @@ class AddonsManager:
|
|||
not enabled.
|
||||
|
||||
Returns:
|
||||
Union[AYONAddon, None]: Enabled addon found by name or None.
|
||||
Union[AYONAddon, Any]: Enabled addon found by name or None.
|
||||
|
||||
"""
|
||||
addon = self.get(addon_name)
|
||||
|
|
@ -608,7 +629,7 @@ class AddonsManager:
|
|||
return addon
|
||||
return default
|
||||
|
||||
def get_enabled_addons(self):
|
||||
def get_enabled_addons(self) -> list[AYONAddon]:
|
||||
"""Enabled addons initialized by the manager.
|
||||
|
||||
Returns:
|
||||
|
|
@ -621,7 +642,7 @@ class AddonsManager:
|
|||
if addon.enabled
|
||||
]
|
||||
|
||||
def initialize_addons(self):
|
||||
def initialize_addons(self) -> None:
|
||||
"""Import and initialize addons."""
|
||||
# Make sure modules are loaded
|
||||
load_addons()
|
||||
|
|
@ -702,7 +723,7 @@ class AddonsManager:
|
|||
report[self._report_total_key] = time.time() - time_start
|
||||
self._report["Initialization"] = report
|
||||
|
||||
def connect_addons(self):
|
||||
def connect_addons(self) -> None:
|
||||
"""Trigger connection with other enabled addons.
|
||||
|
||||
Addons should handle their interfaces in `connect_with_addons`.
|
||||
|
|
@ -730,7 +751,7 @@ class AddonsManager:
|
|||
report[self._report_total_key] = time.time() - time_start
|
||||
self._report["Connect modules"] = report
|
||||
|
||||
def collect_global_environments(self):
|
||||
def collect_global_environments(self) -> dict[str, str]:
|
||||
"""Helper to collect global environment variabled from modules.
|
||||
|
||||
Returns:
|
||||
|
|
@ -753,7 +774,7 @@ class AddonsManager:
|
|||
module_envs[key] = value
|
||||
return module_envs
|
||||
|
||||
def collect_plugin_paths(self):
|
||||
def collect_plugin_paths(self) -> dict[str, list[str]]:
|
||||
"""Helper to collect all plugins from modules inherited IPluginPaths.
|
||||
|
||||
Unknown keys are logged out.
|
||||
|
|
@ -828,7 +849,7 @@ class AddonsManager:
|
|||
)
|
||||
return output
|
||||
|
||||
def _collect_plugin_paths(self, method_name, *args, **kwargs):
|
||||
def _collect_plugin_paths(self, method_name: str, *args, **kwargs):
|
||||
output = []
|
||||
for addon in self.get_enabled_addons():
|
||||
# Skip addon that do not inherit from `IPluginPaths`
|
||||
|
|
@ -859,7 +880,7 @@ class AddonsManager:
|
|||
output.extend(paths)
|
||||
return output
|
||||
|
||||
def collect_launcher_action_paths(self):
|
||||
def collect_launcher_action_paths(self) -> list[str]:
|
||||
"""Helper to collect launcher action paths from addons.
|
||||
|
||||
Returns:
|
||||
|
|
@ -874,16 +895,16 @@ class AddonsManager:
|
|||
output.insert(0, actions_dir)
|
||||
return output
|
||||
|
||||
def collect_create_plugin_paths(self, host_name):
|
||||
def collect_create_plugin_paths(self, host_name: str) -> list[str]:
|
||||
"""Helper to collect creator plugin paths from addons.
|
||||
|
||||
Args:
|
||||
host_name (str): For which host are creators meant.
|
||||
|
||||
Returns:
|
||||
list: List of creator plugin paths.
|
||||
"""
|
||||
list[str]: List of creator plugin paths.
|
||||
|
||||
"""
|
||||
return self._collect_plugin_paths(
|
||||
"get_create_plugin_paths",
|
||||
host_name
|
||||
|
|
@ -891,37 +912,37 @@ class AddonsManager:
|
|||
|
||||
collect_creator_plugin_paths = collect_create_plugin_paths
|
||||
|
||||
def collect_load_plugin_paths(self, host_name):
|
||||
def collect_load_plugin_paths(self, host_name: str) -> list[str]:
|
||||
"""Helper to collect load plugin paths from addons.
|
||||
|
||||
Args:
|
||||
host_name (str): For which host are load plugins meant.
|
||||
|
||||
Returns:
|
||||
list: List of load plugin paths.
|
||||
"""
|
||||
list[str]: List of load plugin paths.
|
||||
|
||||
"""
|
||||
return self._collect_plugin_paths(
|
||||
"get_load_plugin_paths",
|
||||
host_name
|
||||
)
|
||||
|
||||
def collect_publish_plugin_paths(self, host_name):
|
||||
def collect_publish_plugin_paths(self, host_name: str) -> list[str]:
|
||||
"""Helper to collect load plugin paths from addons.
|
||||
|
||||
Args:
|
||||
host_name (str): For which host are load plugins meant.
|
||||
|
||||
Returns:
|
||||
list: List of pyblish plugin paths.
|
||||
"""
|
||||
list[str]: List of pyblish plugin paths.
|
||||
|
||||
"""
|
||||
return self._collect_plugin_paths(
|
||||
"get_publish_plugin_paths",
|
||||
host_name
|
||||
)
|
||||
|
||||
def collect_inventory_action_paths(self, host_name):
|
||||
def collect_inventory_action_paths(self, host_name: str) -> list[str]:
|
||||
"""Helper to collect load plugin paths from addons.
|
||||
|
||||
Args:
|
||||
|
|
@ -929,21 +950,21 @@ class AddonsManager:
|
|||
|
||||
Returns:
|
||||
list: List of pyblish plugin paths.
|
||||
"""
|
||||
|
||||
"""
|
||||
return self._collect_plugin_paths(
|
||||
"get_inventory_action_paths",
|
||||
host_name
|
||||
)
|
||||
|
||||
def get_host_addon(self, host_name):
|
||||
def get_host_addon(self, host_name: str) -> Optional[AYONAddon]:
|
||||
"""Find host addon by host name.
|
||||
|
||||
Args:
|
||||
host_name (str): Host name for which is found host addon.
|
||||
|
||||
Returns:
|
||||
Union[AYONAddon, None]: Found host addon by name or `None`.
|
||||
Optional[AYONAddon]: Found host addon by name or `None`.
|
||||
"""
|
||||
|
||||
for addon in self.get_enabled_addons():
|
||||
|
|
@ -954,21 +975,21 @@ class AddonsManager:
|
|||
return addon
|
||||
return None
|
||||
|
||||
def get_host_names(self):
|
||||
def get_host_names(self) -> set[str]:
|
||||
"""List of available host names based on host addons.
|
||||
|
||||
Returns:
|
||||
Iterable[str]: All available host names based on enabled addons
|
||||
set[str]: All available host names based on enabled addons
|
||||
inheriting 'IHostAddon'.
|
||||
"""
|
||||
|
||||
"""
|
||||
return {
|
||||
addon.host_name
|
||||
for addon in self.get_enabled_addons()
|
||||
if isinstance(addon, IHostAddon)
|
||||
}
|
||||
|
||||
def print_report(self):
|
||||
def print_report(self) -> None:
|
||||
"""Print out report of time spent on addons initialization parts.
|
||||
|
||||
Reporting is not automated must be implemented for each initialization
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue