mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
AYON: Small fixes (#4841)
* us constants from ayon api for environments * updated ayon api * define 'BUILTIN_OCIO_ROOT' in ayon start script * fox missing modules settings * use window open on QApplication exec * fix graphql queries * implemented 'get_archived_assets'
This commit is contained in:
parent
20bb87bf7d
commit
899f9965e4
18 changed files with 1550 additions and 340 deletions
|
|
@ -74,7 +74,6 @@ if "--headless" in sys.argv:
|
|||
elif os.getenv("OPENPYPE_HEADLESS_MODE") != "1":
|
||||
os.environ.pop("OPENPYPE_HEADLESS_MODE", None)
|
||||
|
||||
|
||||
IS_BUILT_APPLICATION = getattr(sys, "frozen", False)
|
||||
HEADLESS_MODE_ENABLED = os.environ.get("OPENPYPE_HEADLESS_MODE") == "1"
|
||||
SILENT_MODE_ENABLED = any(arg in _silent_commands for arg in sys.argv)
|
||||
|
|
@ -137,6 +136,14 @@ os.environ["OPENPYPE_REPOS_ROOT"] = AYON_ROOT
|
|||
os.environ["AVALON_LABEL"] = "AYON"
|
||||
# Set name of pyblish UI import
|
||||
os.environ["PYBLISH_GUI"] = "pyblish_pype"
|
||||
# Set builtin OCIO root
|
||||
os.environ["BUILTIN_OCIO_ROOT"] = os.path.join(
|
||||
AYON_ROOT,
|
||||
"vendor",
|
||||
"bin",
|
||||
"ocioconfig",
|
||||
"OpenColorIOConfigs"
|
||||
)
|
||||
|
||||
import blessed # noqa: E402
|
||||
import certifi # noqa: E402
|
||||
|
|
@ -183,6 +190,7 @@ if not os.getenv("SSL_CERT_FILE"):
|
|||
elif os.getenv("SSL_CERT_FILE") != certifi.where():
|
||||
_print("--- your system is set to use custom CA certificate bundle.")
|
||||
|
||||
from ayon_api.constants import SERVER_URL_ENV_KEY, SERVER_API_ENV_KEY
|
||||
from ayon_common.connection.credentials import (
|
||||
ask_to_login_ui,
|
||||
add_server,
|
||||
|
|
@ -252,12 +260,12 @@ def _connect_to_ayon_server():
|
|||
if HEADLESS_MODE_ENABLED:
|
||||
_print("!!! Cannot open v4 Login dialog in headless mode.")
|
||||
_print((
|
||||
"!!! Please use `AYON_SERVER_URL` to specify server address"
|
||||
" and 'AYON_TOKEN' to specify user's token."
|
||||
))
|
||||
"!!! Please use `{}` to specify server address"
|
||||
" and '{}' to specify user's token."
|
||||
).format(SERVER_URL_ENV_KEY, SERVER_API_ENV_KEY))
|
||||
sys.exit(1)
|
||||
|
||||
current_url = os.environ.get("AYON_SERVER_URL")
|
||||
current_url = os.environ.get(SERVER_URL_ENV_KEY)
|
||||
url, token, username = ask_to_login_ui(current_url, always_on_top=True)
|
||||
if url is not None and token is not None:
|
||||
confirm_server_login(url, token, username)
|
||||
|
|
@ -345,10 +353,10 @@ def boot():
|
|||
t.echo(i)
|
||||
|
||||
try:
|
||||
cli.main(obj={}, prog_name="openpype")
|
||||
cli.main(obj={}, prog_name="ayon")
|
||||
except Exception: # noqa
|
||||
exc_info = sys.exc_info()
|
||||
_print("!!! OpenPype crashed:")
|
||||
_print("!!! AYON crashed:")
|
||||
traceback.print_exception(*exc_info)
|
||||
sys.exit(1)
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ from typing import Optional, Union, Any
|
|||
|
||||
import ayon_api
|
||||
|
||||
from ayon_api.constants import SERVER_URL_ENV_KEY, SERVER_API_ENV_KEY
|
||||
from ayon_api.exceptions import UrlError
|
||||
from ayon_api.utils import (
|
||||
validate_url,
|
||||
|
|
@ -383,7 +384,7 @@ def load_environments():
|
|||
"""Load environments on startup.
|
||||
|
||||
Handle environments needed for connection with server. Environments are
|
||||
'AYON_SERVER_URL' and 'AYON_TOKEN'.
|
||||
'AYON_SERVER_URL' and 'AYON_API_KEY'.
|
||||
|
||||
Server is looked up from environment. Already set environent is not
|
||||
changed. If environemnt is not filled then last server stored in appdirs
|
||||
|
|
@ -394,16 +395,16 @@ def load_environments():
|
|||
based on server url.
|
||||
"""
|
||||
|
||||
server_url = os.environ.get("AYON_SERVER_URL")
|
||||
server_url = os.environ.get(SERVER_URL_ENV_KEY)
|
||||
if not server_url:
|
||||
server_url = get_last_server()
|
||||
if not server_url:
|
||||
return
|
||||
os.environ["AYON_SERVER_URL"] = server_url
|
||||
os.environ[SERVER_URL_ENV_KEY] = server_url
|
||||
|
||||
if not os.environ.get("AYON_TOKEN"):
|
||||
if not os.environ.get(SERVER_API_ENV_KEY):
|
||||
if token := load_token(server_url):
|
||||
os.environ["AYON_TOKEN"] = token
|
||||
os.environ[SERVER_API_ENV_KEY] = token
|
||||
|
||||
|
||||
def set_environments(url: str, token: str):
|
||||
|
|
@ -441,7 +442,7 @@ def need_server_or_login() -> bool:
|
|||
bool: 'True' if server and token are available. Otherwise 'False'.
|
||||
"""
|
||||
|
||||
server_url = os.environ.get("AYON_SERVER_URL")
|
||||
server_url = os.environ.get(SERVER_URL_ENV_KEY)
|
||||
if not server_url:
|
||||
return True
|
||||
|
||||
|
|
@ -450,12 +451,14 @@ def need_server_or_login() -> bool:
|
|||
except UrlError:
|
||||
return True
|
||||
|
||||
token = os.environ.get("AYON_TOKEN")
|
||||
token = os.environ.get(SERVER_API_ENV_KEY)
|
||||
if token:
|
||||
return not is_token_valid(server_url, token)
|
||||
|
||||
token = load_token(server_url)
|
||||
return not is_token_valid(server_url, token)
|
||||
if token:
|
||||
return not is_token_valid(server_url, token)
|
||||
return True
|
||||
|
||||
|
||||
def confirm_server_login(url, token, username):
|
||||
|
|
|
|||
|
|
@ -674,29 +674,14 @@ def ask_to_login(url=None, username=None, always_on_top=False):
|
|||
if username:
|
||||
window.set_username(username)
|
||||
|
||||
_output = {"out": None}
|
||||
|
||||
def _exec_window():
|
||||
window.exec_()
|
||||
result = window.result()
|
||||
out_url, out_token, out_username, _logged_out = result
|
||||
_output["out"] = out_url, out_token, out_username
|
||||
return _output["out"]
|
||||
|
||||
# Use QTimer to exec dialog if application is not running yet
|
||||
# - it is not possible to call 'exec_' on dialog without running app
|
||||
# - it is but the window is stuck
|
||||
if not app_instance.startingUp():
|
||||
return _exec_window()
|
||||
|
||||
timer = QtCore.QTimer()
|
||||
timer.setSingleShot(True)
|
||||
timer.timeout.connect(_exec_window)
|
||||
timer.start()
|
||||
# This can become main Qt loop. Maybe should live elsewhere
|
||||
app_instance.exec_()
|
||||
|
||||
return _output["out"]
|
||||
window.exec_()
|
||||
else:
|
||||
window.open()
|
||||
app_instance.exec_()
|
||||
result = window.result()
|
||||
out_url, out_token, out_username, _ = result
|
||||
return out_url, out_token, out_username
|
||||
|
||||
|
||||
def change_user(url, username, api_key, always_on_top=False):
|
||||
|
|
@ -735,23 +720,10 @@ def change_user(url, username, api_key, always_on_top=False):
|
|||
)
|
||||
window.set_logged_in(True, url, username, api_key)
|
||||
|
||||
_output = {"out": None}
|
||||
|
||||
def _exec_window():
|
||||
window.exec_()
|
||||
_output["out"] = window.result()
|
||||
return _output["out"]
|
||||
|
||||
# Use QTimer to exec dialog if application is not running yet
|
||||
# - it is not possible to call 'exec_' on dialog without running app
|
||||
# - it is but the window is stuck
|
||||
if not app_instance.startingUp():
|
||||
return _exec_window()
|
||||
|
||||
timer = QtCore.QTimer()
|
||||
timer.setSingleShot(True)
|
||||
timer.timeout.connect(_exec_window)
|
||||
timer.start()
|
||||
# This can become main Qt loop. Maybe should live elsewhere
|
||||
app_instance.exec_()
|
||||
return _output["out"]
|
||||
window.exec_()
|
||||
else:
|
||||
window.open()
|
||||
# This can become main Qt loop. Maybe should live elsewhere
|
||||
app_instance.exec_()
|
||||
return window.result()
|
||||
|
|
|
|||
|
|
@ -216,8 +216,21 @@ def get_assets(
|
|||
yield convert_v4_folder_to_v3(folder, project_name)
|
||||
|
||||
|
||||
def get_archived_assets(*args, **kwargs):
|
||||
raise NotImplementedError("'get_archived_assets' not implemented")
|
||||
def get_archived_assets(
|
||||
project_name,
|
||||
asset_ids=None,
|
||||
asset_names=None,
|
||||
parent_ids=None,
|
||||
fields=None
|
||||
):
|
||||
return get_assets(
|
||||
project_name,
|
||||
asset_ids,
|
||||
asset_names,
|
||||
parent_ids,
|
||||
True,
|
||||
fields
|
||||
)
|
||||
|
||||
|
||||
def get_asset_ids_with_subsets(project_name, asset_ids=None):
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ def folders_tasks_graphql_query(fields):
|
|||
project_field = query.add_field("project")
|
||||
project_field.set_filter("name", project_name_var)
|
||||
|
||||
folders_field = project_field.add_field("folders", has_edges=True)
|
||||
folders_field = project_field.add_field_with_edges("folders")
|
||||
folders_field.set_filter("ids", folder_ids_var)
|
||||
folders_field.set_filter("parentIds", parent_folder_ids_var)
|
||||
folders_field.set_filter("names", folder_names_var)
|
||||
|
|
@ -25,7 +25,7 @@ def folders_tasks_graphql_query(fields):
|
|||
|
||||
fields = set(fields)
|
||||
fields.discard("tasks")
|
||||
tasks_field = folders_field.add_field("tasks", has_edges=True)
|
||||
tasks_field = folders_field.add_field_with_edges("tasks")
|
||||
tasks_field.add_field("name")
|
||||
tasks_field.add_field("taskType")
|
||||
|
||||
|
|
|
|||
|
|
@ -857,7 +857,7 @@ def delete_project(project_name, con=None):
|
|||
return con.delete_project(project_name)
|
||||
|
||||
|
||||
def create_thumbnail(project_name, src_filepath, con=None):
|
||||
def create_thumbnail(project_name, src_filepath, thumbnail_id=None, con=None):
|
||||
if con is None:
|
||||
con = get_server_api_connection()
|
||||
return con.create_thumbnail(project_name, src_filepath)
|
||||
return con.create_thumbnail(project_name, src_filepath, thumbnail_id)
|
||||
|
|
|
|||
|
|
@ -253,19 +253,6 @@ def _convert_royalrender_system_settings(ayon_settings, output):
|
|||
def _convert_modules_system(
|
||||
ayon_settings, output, addon_versions, default_settings
|
||||
):
|
||||
# TODO remove when not needed
|
||||
# - these modules are not and won't be in AYON avaialble
|
||||
for module_name in (
|
||||
"addon_paths",
|
||||
"avalon",
|
||||
"job_queue",
|
||||
"log_viewer",
|
||||
"project_manager",
|
||||
):
|
||||
output["modules"][module_name] = (
|
||||
default_settings["modules"][module_name]
|
||||
)
|
||||
|
||||
# TODO add all modules
|
||||
# TODO add 'enabled' values
|
||||
for key, func in (
|
||||
|
|
@ -282,6 +269,11 @@ def _convert_modules_system(
|
|||
func(ayon_settings, output)
|
||||
|
||||
output_modules = output["modules"]
|
||||
# TODO remove when not needed
|
||||
for module_name, value in default_settings["modules"].items():
|
||||
if module_name not in output_modules:
|
||||
output_modules[module_name] = value
|
||||
|
||||
for module_name, value in default_settings["modules"].items():
|
||||
if "enabled" not in value or module_name not in output_modules:
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ from ._api import (
|
|||
query_graphql,
|
||||
|
||||
get_addons_info,
|
||||
get_addon_url,
|
||||
download_addon_private_file,
|
||||
|
||||
get_dependencies_info,
|
||||
|
|
@ -121,11 +122,35 @@ from ._api import (
|
|||
get_representation_parents,
|
||||
get_repre_ids_by_context_filters,
|
||||
|
||||
create_thumbnail,
|
||||
get_thumbnail,
|
||||
get_folder_thumbnail,
|
||||
get_version_thumbnail,
|
||||
get_workfile_thumbnail,
|
||||
create_thumbnail,
|
||||
update_thumbnail,
|
||||
|
||||
get_full_link_type_name,
|
||||
get_link_types,
|
||||
get_link_type,
|
||||
create_link_type,
|
||||
delete_link_type,
|
||||
make_sure_link_type_exists,
|
||||
|
||||
create_link,
|
||||
delete_link,
|
||||
get_entities_links,
|
||||
get_folder_links,
|
||||
get_folders_links,
|
||||
get_task_links,
|
||||
get_tasks_links,
|
||||
get_subset_links,
|
||||
get_subsets_links,
|
||||
get_version_links,
|
||||
get_versions_links,
|
||||
get_representations_links,
|
||||
get_representation_links,
|
||||
|
||||
send_batch_operations,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -184,6 +209,7 @@ __all__ = (
|
|||
"query_graphql",
|
||||
|
||||
"get_addons_info",
|
||||
"get_addon_url",
|
||||
"download_addon_private_file",
|
||||
|
||||
"get_dependencies_info",
|
||||
|
|
@ -248,9 +274,33 @@ __all__ = (
|
|||
"get_representation_parents",
|
||||
"get_repre_ids_by_context_filters",
|
||||
|
||||
"create_thumbnail",
|
||||
"get_thumbnail",
|
||||
"get_folder_thumbnail",
|
||||
"get_version_thumbnail",
|
||||
"get_workfile_thumbnail",
|
||||
"create_thumbnail",
|
||||
"update_thumbnail",
|
||||
|
||||
"get_full_link_type_name",
|
||||
"get_link_types",
|
||||
"get_link_type",
|
||||
"create_link_type",
|
||||
"delete_link_type",
|
||||
"make_sure_link_type_exists",
|
||||
|
||||
"create_link",
|
||||
"delete_link",
|
||||
"get_entities_links",
|
||||
"get_folder_links",
|
||||
"get_folders_links",
|
||||
"get_task_links",
|
||||
"get_tasks_links",
|
||||
"get_subset_links",
|
||||
"get_subsets_links",
|
||||
"get_version_links",
|
||||
"get_versions_links",
|
||||
"get_representations_links",
|
||||
"get_representation_links",
|
||||
|
||||
"send_batch_operations",
|
||||
)
|
||||
|
|
|
|||
276
openpype/vendor/python/common/ayon_api/_api.py
vendored
276
openpype/vendor/python/common/ayon_api/_api.py
vendored
|
|
@ -11,7 +11,7 @@ import socket
|
|||
|
||||
from .constants import (
|
||||
SERVER_URL_ENV_KEY,
|
||||
SERVER_TOKEN_ENV_KEY,
|
||||
SERVER_API_ENV_KEY,
|
||||
)
|
||||
from .server_api import ServerAPI
|
||||
from .exceptions import FailedServiceInit
|
||||
|
|
@ -21,7 +21,7 @@ class GlobalServerAPI(ServerAPI):
|
|||
"""Extended server api which also handles storing tokens and url.
|
||||
|
||||
Created object expect to have set environment variables
|
||||
'AYON_SERVER_URL'. Also is expecting filled 'AYON_TOKEN'
|
||||
'AYON_SERVER_URL'. Also is expecting filled 'AYON_API_KEY'
|
||||
but that can be filled afterwards with calling 'login' method.
|
||||
"""
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ class GlobalServerAPI(ServerAPI):
|
|||
previous_token = self._access_token
|
||||
super(GlobalServerAPI, self).login(username, password)
|
||||
if self.has_valid_token and previous_token != self._access_token:
|
||||
os.environ[SERVER_TOKEN_ENV_KEY] = self._access_token
|
||||
os.environ[SERVER_API_ENV_KEY] = self._access_token
|
||||
|
||||
@staticmethod
|
||||
def get_url():
|
||||
|
|
@ -52,7 +52,7 @@ class GlobalServerAPI(ServerAPI):
|
|||
|
||||
@staticmethod
|
||||
def get_token():
|
||||
return os.environ.get(SERVER_TOKEN_ENV_KEY)
|
||||
return os.environ.get(SERVER_API_ENV_KEY)
|
||||
|
||||
@staticmethod
|
||||
def set_environments(url, token):
|
||||
|
|
@ -64,7 +64,7 @@ class GlobalServerAPI(ServerAPI):
|
|||
"""
|
||||
|
||||
os.environ[SERVER_URL_ENV_KEY] = url or ""
|
||||
os.environ[SERVER_TOKEN_ENV_KEY] = token or ""
|
||||
os.environ[SERVER_API_ENV_KEY] = token or ""
|
||||
|
||||
|
||||
class GlobalContext:
|
||||
|
|
@ -151,7 +151,7 @@ class ServiceContext:
|
|||
connect=True
|
||||
):
|
||||
token = cls.get_value_from_envs(
|
||||
("AY_API_KEY", "AYON_TOKEN"),
|
||||
("AY_API_KEY", "AYON_API_KEY"),
|
||||
token
|
||||
)
|
||||
server_url = cls.get_value_from_envs(
|
||||
|
|
@ -322,7 +322,7 @@ def get_server_api_connection():
|
|||
"""Access to global scope object of GlobalServerAPI.
|
||||
|
||||
This access expect to have set environment variables 'AYON_SERVER_URL'
|
||||
and 'AYON_TOKEN'.
|
||||
and 'AYON_API_KEY'.
|
||||
|
||||
Returns:
|
||||
GlobalServerAPI: Object of connection to server.
|
||||
|
|
@ -521,6 +521,11 @@ def get_addons_info(*args, **kwargs):
|
|||
return con.get_addons_info(*args, **kwargs)
|
||||
|
||||
|
||||
def get_addon_url(addon_name, addon_version, *subpaths):
|
||||
con = get_server_api_connection()
|
||||
return con.get_addon_url(addon_name, addon_version, *subpaths)
|
||||
|
||||
|
||||
def download_addon_private_file(*args, **kwargs):
|
||||
con = get_server_api_connection()
|
||||
return con.download_addon_private_file(*args, **kwargs)
|
||||
|
|
@ -776,11 +781,6 @@ def delete_project(project_name):
|
|||
return con.delete_project(project_name)
|
||||
|
||||
|
||||
def create_thumbnail(project_name, src_filepath):
|
||||
con = get_server_api_connection()
|
||||
return con.create_thumbnail(project_name, src_filepath)
|
||||
|
||||
|
||||
def get_thumbnail(project_name, entity_type, entity_id, thumbnail_id=None):
|
||||
con = get_server_api_connection()
|
||||
con.get_thumbnail(project_name, entity_type, entity_id, thumbnail_id)
|
||||
|
|
@ -801,11 +801,259 @@ def get_workfile_thumbnail(project_name, workfile_id, thumbnail_id=None):
|
|||
return con.get_workfile_thumbnail(project_name, workfile_id, thumbnail_id)
|
||||
|
||||
|
||||
def create_thumbnail(project_name, src_filepath):
|
||||
def create_thumbnail(project_name, src_filepath, thumbnail_id=None):
|
||||
con = get_server_api_connection()
|
||||
return con.create_thumbnail(project_name, src_filepath)
|
||||
return con.create_thumbnail(project_name, src_filepath, thumbnail_id)
|
||||
|
||||
|
||||
def update_thumbnail(project_name, thumbnail_id, src_filepath):
|
||||
con = get_server_api_connection()
|
||||
return con.update_thumbnail(project_name, thumbnail_id, src_filepath)
|
||||
|
||||
|
||||
def get_default_fields_for_type(entity_type):
|
||||
con = get_server_api_connection()
|
||||
return con.get_default_fields_for_type(entity_type)
|
||||
|
||||
|
||||
def get_full_link_type_name(link_type_name, input_type, output_type):
|
||||
con = get_server_api_connection()
|
||||
return con.get_full_link_type_name(
|
||||
link_type_name, input_type, output_type)
|
||||
|
||||
|
||||
def get_link_types(project_name):
|
||||
con = get_server_api_connection()
|
||||
return con.get_link_types(project_name)
|
||||
|
||||
|
||||
def get_link_type(project_name, link_type_name, input_type, output_type):
|
||||
con = get_server_api_connection()
|
||||
return con.get_link_type(
|
||||
project_name, link_type_name, input_type, output_type)
|
||||
|
||||
|
||||
def create_link_type(
|
||||
project_name, link_type_name, input_type, output_type, data=None):
|
||||
con = get_server_api_connection()
|
||||
return con.create_link_type(
|
||||
project_name, link_type_name, input_type, output_type, data=data)
|
||||
|
||||
|
||||
def delete_link_type(project_name, link_type_name, input_type, output_type):
|
||||
con = get_server_api_connection()
|
||||
return con.delete_link_type(
|
||||
project_name, link_type_name, input_type, output_type)
|
||||
|
||||
|
||||
def make_sure_link_type_exists(
|
||||
project_name, link_type_name, input_type, output_type, data=None
|
||||
):
|
||||
con = get_server_api_connection()
|
||||
return con.make_sure_link_type_exists(
|
||||
project_name, link_type_name, input_type, output_type, data=data
|
||||
)
|
||||
|
||||
|
||||
def create_link(
|
||||
project_name,
|
||||
link_type_name,
|
||||
input_id,
|
||||
input_type,
|
||||
output_id,
|
||||
output_type
|
||||
):
|
||||
con = get_server_api_connection()
|
||||
return con.create_link(
|
||||
project_name,
|
||||
link_type_name,
|
||||
input_id, input_type,
|
||||
output_id, output_type
|
||||
)
|
||||
|
||||
|
||||
def delete_link(project_name, link_id):
|
||||
con = get_server_api_connection()
|
||||
return con.delete_link(project_name, link_id)
|
||||
|
||||
|
||||
def get_entities_links(
|
||||
project_name,
|
||||
entity_type,
|
||||
entity_ids=None,
|
||||
link_types=None,
|
||||
link_direction=None
|
||||
):
|
||||
con = get_server_api_connection()
|
||||
return con.get_entities_links(
|
||||
project_name,
|
||||
entity_type,
|
||||
entity_ids,
|
||||
link_types,
|
||||
link_direction
|
||||
)
|
||||
|
||||
|
||||
def get_folders_links(
|
||||
project_name,
|
||||
folder_ids=None,
|
||||
link_types=None,
|
||||
link_direction=None
|
||||
):
|
||||
con = get_server_api_connection()
|
||||
return con.get_folders_links(
|
||||
project_name,
|
||||
folder_ids,
|
||||
link_types,
|
||||
link_direction
|
||||
)
|
||||
|
||||
|
||||
def get_folder_links(
|
||||
project_name,
|
||||
folder_id,
|
||||
link_types=None,
|
||||
link_direction=None
|
||||
):
|
||||
con = get_server_api_connection()
|
||||
return con.get_folder_links(
|
||||
project_name,
|
||||
folder_id,
|
||||
link_types,
|
||||
link_direction
|
||||
)
|
||||
|
||||
|
||||
def get_tasks_links(
|
||||
project_name,
|
||||
task_ids=None,
|
||||
link_types=None,
|
||||
link_direction=None
|
||||
):
|
||||
con = get_server_api_connection()
|
||||
return con.get_tasks_links(
|
||||
project_name,
|
||||
task_ids,
|
||||
link_types,
|
||||
link_direction
|
||||
)
|
||||
|
||||
|
||||
def get_task_links(
|
||||
project_name,
|
||||
task_id,
|
||||
link_types=None,
|
||||
link_direction=None
|
||||
):
|
||||
con = get_server_api_connection()
|
||||
return con.get_task_links(
|
||||
project_name,
|
||||
task_id,
|
||||
link_types,
|
||||
link_direction
|
||||
)
|
||||
|
||||
|
||||
def get_subsets_links(
|
||||
project_name,
|
||||
subset_ids=None,
|
||||
link_types=None,
|
||||
link_direction=None
|
||||
):
|
||||
con = get_server_api_connection()
|
||||
return con.get_subsets_links(
|
||||
project_name,
|
||||
subset_ids,
|
||||
link_types,
|
||||
link_direction
|
||||
)
|
||||
|
||||
|
||||
def get_subset_links(
|
||||
project_name,
|
||||
subset_id,
|
||||
link_types=None,
|
||||
link_direction=None
|
||||
):
|
||||
con = get_server_api_connection()
|
||||
return con.get_subset_links(
|
||||
project_name,
|
||||
subset_id,
|
||||
link_types,
|
||||
link_direction
|
||||
)
|
||||
|
||||
|
||||
def get_versions_links(
|
||||
project_name,
|
||||
version_ids=None,
|
||||
link_types=None,
|
||||
link_direction=None
|
||||
):
|
||||
con = get_server_api_connection()
|
||||
return con.get_versions_links(
|
||||
project_name,
|
||||
version_ids,
|
||||
link_types,
|
||||
link_direction
|
||||
)
|
||||
|
||||
|
||||
def get_version_links(
|
||||
project_name,
|
||||
version_id,
|
||||
link_types=None,
|
||||
link_direction=None
|
||||
):
|
||||
con = get_server_api_connection()
|
||||
return con.get_version_links(
|
||||
project_name,
|
||||
version_id,
|
||||
link_types,
|
||||
link_direction
|
||||
)
|
||||
|
||||
|
||||
def get_representations_links(
|
||||
project_name,
|
||||
representation_ids=None,
|
||||
link_types=None,
|
||||
link_direction=None
|
||||
):
|
||||
con = get_server_api_connection()
|
||||
return con.get_representations_links(
|
||||
project_name,
|
||||
representation_ids,
|
||||
link_types,
|
||||
link_direction
|
||||
)
|
||||
|
||||
|
||||
def get_representation_links(
|
||||
project_name,
|
||||
representation_id,
|
||||
link_types=None,
|
||||
link_direction=None
|
||||
):
|
||||
con = get_server_api_connection()
|
||||
return con.get_representation_links(
|
||||
project_name,
|
||||
representation_id,
|
||||
link_types,
|
||||
link_direction
|
||||
)
|
||||
|
||||
|
||||
def send_batch_operations(
|
||||
project_name,
|
||||
operations,
|
||||
can_fail=False,
|
||||
raise_on_fail=True
|
||||
):
|
||||
con = get_server_api_connection()
|
||||
return con.send_batch_operations(
|
||||
project_name,
|
||||
operations,
|
||||
can_fail=can_fail,
|
||||
raise_on_fail=raise_on_fail
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
# Environments where server url and api key are stored for global connection
|
||||
SERVER_URL_ENV_KEY = "AYON_SERVER_URL"
|
||||
SERVER_TOKEN_ENV_KEY = "AYON_TOKEN"
|
||||
SERVER_API_ENV_KEY = "AYON_API_KEY"
|
||||
# Backwards compatibility
|
||||
SERVER_TOKEN_ENV_KEY = SERVER_API_ENV_KEY
|
||||
|
||||
# --- Project ---
|
||||
DEFAULT_PROJECT_FIELDS = {
|
||||
|
|
@ -102,4 +105,4 @@ DEFAULT_EVENT_FIELDS = {
|
|||
"topic",
|
||||
"updatedAt",
|
||||
"user",
|
||||
}
|
||||
}
|
||||
|
|
|
|||
156
openpype/vendor/python/common/ayon_api/entity_hub.py
vendored
156
openpype/vendor/python/common/ayon_api/entity_hub.py
vendored
|
|
@ -1,6 +1,6 @@
|
|||
import copy
|
||||
import collections
|
||||
from abc import ABCMeta, abstractmethod, abstractproperty
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
import six
|
||||
from ._api import get_server_api_connection
|
||||
|
|
@ -52,17 +52,35 @@ class EntityHub(object):
|
|||
|
||||
@property
|
||||
def allow_data_changes(self):
|
||||
"""Entity hub allows changes of 'data' key on entities."""
|
||||
"""Entity hub allows changes of 'data' key on entities.
|
||||
|
||||
Data are private and not all users may have access to them. Also to get
|
||||
'data' for entity is required to use REST api calls, which means to
|
||||
query each entity on-by-one from server.
|
||||
|
||||
Returns:
|
||||
bool: Data changes are allowed.
|
||||
"""
|
||||
|
||||
return self._allow_data_changes
|
||||
|
||||
@property
|
||||
def project_name(self):
|
||||
"""Project name which is maintained by hub.
|
||||
|
||||
Returns:
|
||||
str: Name of project.
|
||||
"""
|
||||
|
||||
return self._project_name
|
||||
|
||||
@property
|
||||
def project_entity(self):
|
||||
"""Project entity."""
|
||||
"""Project entity.
|
||||
|
||||
Returns:
|
||||
ProjectEntity: Project entity.
|
||||
"""
|
||||
|
||||
if self._project_entity is UNKNOWN_VALUE:
|
||||
self.fill_project_from_server()
|
||||
|
|
@ -187,6 +205,12 @@ class EntityHub(object):
|
|||
|
||||
@property
|
||||
def entities(self):
|
||||
"""Iterator over available entities.
|
||||
|
||||
Returns:
|
||||
Iterator[BaseEntity]: All queried/created entities cached in hub.
|
||||
"""
|
||||
|
||||
for entity in self._entities_by_id.values():
|
||||
yield entity
|
||||
|
||||
|
|
@ -194,8 +218,21 @@ class EntityHub(object):
|
|||
"""Create folder object and add it to entity hub.
|
||||
|
||||
Args:
|
||||
parent (Union[ProjectEntity, FolderEntity]): Parent of added
|
||||
folder.
|
||||
folder_type (str): Type of folder. Folder type must be available in
|
||||
config of project folder types.
|
||||
entity_id (Union[str, None]): Id of the entity. New id is created if
|
||||
not passed.
|
||||
parent_id (Union[str, None]): Id of parent entity.
|
||||
name (str): Name of entity.
|
||||
label (Optional[str]): Folder label.
|
||||
path (Optional[str]): Folder path. Path consist of all parent names
|
||||
with slash('/') used as separator.
|
||||
attribs (Dict[str, Any]): Attribute values.
|
||||
data (Dict[str, Any]): Entity data (custom data).
|
||||
thumbnail_id (Union[str, None]): Id of entity's thumbnail.
|
||||
active (bool): Is entity active.
|
||||
created (Optional[bool]): Entity is new. When 'None' is passed the
|
||||
value is defined based on value of 'entity_id'.
|
||||
|
||||
Returns:
|
||||
FolderEntity: Added folder entity.
|
||||
|
|
@ -208,6 +245,27 @@ class EntityHub(object):
|
|||
return folder_entity
|
||||
|
||||
def add_new_task(self, *args, created=True, **kwargs):
|
||||
"""Create folder object and add it to entity hub.
|
||||
|
||||
Args:
|
||||
task_type (str): Type of task. Task type must be available in
|
||||
config of project folder types.
|
||||
entity_id (Union[str, None]): Id of the entity. New id is created if
|
||||
not passed.
|
||||
parent_id (Union[str, None]): Id of parent entity.
|
||||
name (str): Name of entity.
|
||||
label (Optional[str]): Folder label.
|
||||
attribs (Dict[str, Any]): Attribute values.
|
||||
data (Dict[str, Any]): Entity data (custom data).
|
||||
thumbnail_id (Union[str, None]): Id of entity's thumbnail.
|
||||
active (bool): Is entity active.
|
||||
created (Optional[bool]): Entity is new. When 'None' is passed the
|
||||
value is defined based on value of 'entity_id'.
|
||||
|
||||
Returns:
|
||||
TaskEntity: Added task entity.
|
||||
"""
|
||||
|
||||
task_entity = TaskEntity(
|
||||
*args, **kwargs, created=created, entity_hub=self
|
||||
)
|
||||
|
|
@ -428,7 +486,7 @@ class EntityHub(object):
|
|||
if parent_id is None:
|
||||
return
|
||||
|
||||
parent = self._entities_by_parent_id.get(parent_id)
|
||||
parent = self._entities_by_id.get(parent_id)
|
||||
if parent is not None:
|
||||
parent.remove_child(entity.id)
|
||||
|
||||
|
|
@ -459,10 +517,12 @@ class EntityHub(object):
|
|||
reset_queue.append(child.id)
|
||||
|
||||
def fill_project_from_server(self):
|
||||
"""Query project from server and create it's entity.
|
||||
"""Query project data from server and create project entity.
|
||||
|
||||
This method will invalidate previous object of Project entity.
|
||||
|
||||
Returns:
|
||||
ProjectEntity: Entity that was created based on queried data.
|
||||
ProjectEntity: Entity that was updated with server data.
|
||||
|
||||
Raises:
|
||||
ValueError: When project was not found on server.
|
||||
|
|
@ -844,17 +904,17 @@ class BaseEntity(object):
|
|||
entity are set as "current data" on server.
|
||||
|
||||
Args:
|
||||
entity_id (Union[str, None]): Id of the entity. New id is created if
|
||||
not passed.
|
||||
parent_id (Union[str, None]): Id of parent entity.
|
||||
name (str): Name of entity.
|
||||
attribs (Dict[str, Any]): Attribute values.
|
||||
data (Dict[str, Any]): Entity data (custom data).
|
||||
parent_id (Union[str, None]): Id of parent entity.
|
||||
entity_id (Union[str, None]): Id of the entity. New id is created if
|
||||
not passed.
|
||||
thumbnail_id (Union[str, None]): Id of entity's thumbnail.
|
||||
active (bool): Is entity active.
|
||||
entity_hub (EntityHub): Object of entity hub which created object of
|
||||
the entity.
|
||||
created (Union[bool, None]): Entity is new. When 'None' is passed the
|
||||
created (Optional[bool]): Entity is new. When 'None' is passed the
|
||||
value is defined based on value of 'entity_id'.
|
||||
"""
|
||||
|
||||
|
|
@ -981,7 +1041,8 @@ class BaseEntity(object):
|
|||
|
||||
return self._entity_hub.project_name
|
||||
|
||||
@abstractproperty
|
||||
@property
|
||||
@abstractmethod
|
||||
def entity_type(self):
|
||||
"""Entity type coresponding to server.
|
||||
|
||||
|
|
@ -991,7 +1052,8 @@ class BaseEntity(object):
|
|||
|
||||
pass
|
||||
|
||||
@abstractproperty
|
||||
@property
|
||||
@abstractmethod
|
||||
def parent_entity_types(self):
|
||||
"""Entity type coresponding to server.
|
||||
|
||||
|
|
@ -1001,7 +1063,8 @@ class BaseEntity(object):
|
|||
|
||||
pass
|
||||
|
||||
@abstractproperty
|
||||
@property
|
||||
@abstractmethod
|
||||
def changes(self):
|
||||
"""Receive entity changes.
|
||||
|
||||
|
|
@ -1331,6 +1394,27 @@ class BaseEntity(object):
|
|||
|
||||
|
||||
class ProjectEntity(BaseEntity):
|
||||
"""Entity representing project on AYON server.
|
||||
|
||||
Args:
|
||||
project_code (str): Project code.
|
||||
library (bool): Is project library project.
|
||||
folder_types (list[dict[str, Any]]): Folder types definition.
|
||||
task_types (list[dict[str, Any]]): Task types definition.
|
||||
entity_id (Optional[str]): Id of the entity. New id is created if
|
||||
not passed.
|
||||
parent_id (Union[str, None]): Id of parent entity.
|
||||
name (str): Name of entity.
|
||||
attribs (Dict[str, Any]): Attribute values.
|
||||
data (Dict[str, Any]): Entity data (custom data).
|
||||
thumbnail_id (Union[str, None]): Id of entity's thumbnail.
|
||||
active (bool): Is entity active.
|
||||
entity_hub (EntityHub): Object of entity hub which created object of
|
||||
the entity.
|
||||
created (Optional[bool]): Entity is new. When 'None' is passed the
|
||||
value is defined based on value of 'entity_id'.
|
||||
"""
|
||||
|
||||
entity_type = "project"
|
||||
parent_entity_types = []
|
||||
# TODO These are hardcoded but maybe should be used from server???
|
||||
|
|
@ -1433,6 +1517,28 @@ class ProjectEntity(BaseEntity):
|
|||
|
||||
|
||||
class FolderEntity(BaseEntity):
|
||||
"""Entity representing a folder on AYON server.
|
||||
|
||||
Args:
|
||||
folder_type (str): Type of folder. Folder type must be available in
|
||||
config of project folder types.
|
||||
entity_id (Union[str, None]): Id of the entity. New id is created if
|
||||
not passed.
|
||||
parent_id (Union[str, None]): Id of parent entity.
|
||||
name (str): Name of entity.
|
||||
attribs (Dict[str, Any]): Attribute values.
|
||||
data (Dict[str, Any]): Entity data (custom data).
|
||||
thumbnail_id (Union[str, None]): Id of entity's thumbnail.
|
||||
active (bool): Is entity active.
|
||||
label (Optional[str]): Folder label.
|
||||
path (Optional[str]): Folder path. Path consist of all parent names
|
||||
with slash('/') used as separator.
|
||||
entity_hub (EntityHub): Object of entity hub which created object of
|
||||
the entity.
|
||||
created (Optional[bool]): Entity is new. When 'None' is passed the
|
||||
value is defined based on value of 'entity_id'.
|
||||
"""
|
||||
|
||||
entity_type = "folder"
|
||||
parent_entity_types = ["folder", "project"]
|
||||
|
||||
|
|
@ -1587,6 +1693,26 @@ class FolderEntity(BaseEntity):
|
|||
|
||||
|
||||
class TaskEntity(BaseEntity):
|
||||
"""Entity representing a task on AYON server.
|
||||
|
||||
Args:
|
||||
task_type (str): Type of task. Task type must be available in config
|
||||
of project task types.
|
||||
entity_id (Union[str, None]): Id of the entity. New id is created if
|
||||
not passed.
|
||||
parent_id (Union[str, None]): Id of parent entity.
|
||||
name (str): Name of entity.
|
||||
label (Optional[str]): Task label.
|
||||
attribs (Dict[str, Any]): Attribute values.
|
||||
data (Dict[str, Any]): Entity data (custom data).
|
||||
thumbnail_id (Union[str, None]): Id of entity's thumbnail.
|
||||
active (bool): Is entity active.
|
||||
entity_hub (EntityHub): Object of entity hub which created object of
|
||||
the entity.
|
||||
created (Optional[bool]): Entity is new. When 'None' is passed the
|
||||
value is defined based on value of 'entity_id'.
|
||||
"""
|
||||
|
||||
entity_type = "task"
|
||||
parent_entity_types = ["folder"]
|
||||
|
||||
|
|
|
|||
|
|
@ -49,4 +49,4 @@ class ServerEvent(object):
|
|||
"payload": self.payload,
|
||||
"finished": self.finished,
|
||||
"store": self.store
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,16 @@ class ServerNotReached(ServerError):
|
|||
pass
|
||||
|
||||
|
||||
class RequestError(Exception):
|
||||
def __init__(self, message, response):
|
||||
self.response = response
|
||||
super(RequestError, self).__init__(message)
|
||||
|
||||
|
||||
class HTTPRequestError(RequestError):
|
||||
pass
|
||||
|
||||
|
||||
class GraphQlQueryFailed(Exception):
|
||||
def __init__(self, errors, query, variables):
|
||||
if variables is None:
|
||||
|
|
@ -94,4 +104,4 @@ class FailedOperations(Exception):
|
|||
|
||||
|
||||
class FailedServiceInit(Exception):
|
||||
pass
|
||||
pass
|
||||
|
|
|
|||
151
openpype/vendor/python/common/ayon_api/graphql.py
vendored
151
openpype/vendor/python/common/ayon_api/graphql.py
vendored
|
|
@ -1,6 +1,6 @@
|
|||
import copy
|
||||
import numbers
|
||||
from abc import ABCMeta, abstractproperty, abstractmethod
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
import six
|
||||
|
||||
|
|
@ -232,21 +232,31 @@ class GraphQlQuery:
|
|||
self._children.append(field)
|
||||
field.set_parent(self)
|
||||
|
||||
def add_field(self, name, has_edges=None):
|
||||
def add_field_with_edges(self, name):
|
||||
"""Add field with edges to query.
|
||||
|
||||
Args:
|
||||
name (str): Field name e.g. 'tasks'.
|
||||
|
||||
Returns:
|
||||
GraphQlQueryEdgeField: Created field object.
|
||||
"""
|
||||
|
||||
item = GraphQlQueryEdgeField(name, self)
|
||||
self.add_obj_field(item)
|
||||
return item
|
||||
|
||||
def add_field(self, name):
|
||||
"""Add field to query.
|
||||
|
||||
Args:
|
||||
name (str): Field name e.g. 'id'.
|
||||
has_edges (bool): Field has edges so it need paging.
|
||||
|
||||
Returns:
|
||||
BaseGraphQlQueryField: Created field object.
|
||||
GraphQlQueryField: Created field object.
|
||||
"""
|
||||
|
||||
if has_edges:
|
||||
item = GraphQlQueryEdgeField(name, self)
|
||||
else:
|
||||
item = GraphQlQueryField(name, self)
|
||||
item = GraphQlQueryField(name, self)
|
||||
self.add_obj_field(item)
|
||||
return item
|
||||
|
||||
|
|
@ -376,7 +386,6 @@ class BaseGraphQlQueryField(object):
|
|||
name (str): Name of field.
|
||||
parent (Union[BaseGraphQlQueryField, GraphQlQuery]): Parent object of a
|
||||
field.
|
||||
has_edges (bool): Field has edges and should handle paging.
|
||||
"""
|
||||
|
||||
def __init__(self, name, parent):
|
||||
|
|
@ -401,6 +410,36 @@ class BaseGraphQlQueryField(object):
|
|||
def __repr__(self):
|
||||
return "<{} {}>".format(self.__class__.__name__, self.path)
|
||||
|
||||
def add_variable(self, key, value_type, value=None):
|
||||
"""Add variable to query.
|
||||
|
||||
Args:
|
||||
key (str): Variable name.
|
||||
value_type (str): Type of expected value in variables. This is
|
||||
graphql type e.g. "[String!]", "Int", "Boolean", etc.
|
||||
value (Any): Default value for variable. Can be changed later.
|
||||
|
||||
Returns:
|
||||
QueryVariable: Created variable object.
|
||||
|
||||
Raises:
|
||||
KeyError: If variable was already added before.
|
||||
"""
|
||||
|
||||
return self._parent.add_variable(key, value_type, value)
|
||||
|
||||
def get_variable(self, key):
|
||||
"""Variable object.
|
||||
|
||||
Args:
|
||||
key (str): Variable name added to headers.
|
||||
|
||||
Returns:
|
||||
QueryVariable: Variable object used in query string.
|
||||
"""
|
||||
|
||||
return self._parent.get_variable(key)
|
||||
|
||||
@property
|
||||
def need_query(self):
|
||||
"""Still need query from server.
|
||||
|
|
@ -414,11 +453,21 @@ class BaseGraphQlQueryField(object):
|
|||
if self._need_query:
|
||||
return True
|
||||
|
||||
for child in self._children:
|
||||
for child in self._children_iter():
|
||||
if child.need_query:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _children_iter(self):
|
||||
"""Iterate over all children fields of object.
|
||||
|
||||
Returns:
|
||||
Iterator[BaseGraphQlQueryField]: Children fields.
|
||||
"""
|
||||
|
||||
for child in self._children:
|
||||
yield child
|
||||
|
||||
def sum_edge_fields(self, max_limit=None):
|
||||
"""Check how many edge fields query has.
|
||||
|
||||
|
|
@ -437,7 +486,7 @@ class BaseGraphQlQueryField(object):
|
|||
if isinstance(self, GraphQlQueryEdgeField):
|
||||
counter = 1
|
||||
|
||||
for child in self._children:
|
||||
for child in self._children_iter():
|
||||
counter += child.sum_edge_fields(max_limit)
|
||||
if max_limit is not None and counter >= max_limit:
|
||||
break
|
||||
|
|
@ -451,7 +500,8 @@ class BaseGraphQlQueryField(object):
|
|||
def indent(self):
|
||||
return self._parent.child_indent + self.offset
|
||||
|
||||
@abstractproperty
|
||||
@property
|
||||
@abstractmethod
|
||||
def child_indent(self):
|
||||
pass
|
||||
|
||||
|
|
@ -459,13 +509,14 @@ class BaseGraphQlQueryField(object):
|
|||
def query_item(self):
|
||||
return self._query_item
|
||||
|
||||
@abstractproperty
|
||||
@property
|
||||
@abstractmethod
|
||||
def has_edges(self):
|
||||
pass
|
||||
|
||||
@property
|
||||
def child_has_edges(self):
|
||||
for child in self._children:
|
||||
for child in self._children_iter():
|
||||
if child.has_edges or child.child_has_edges:
|
||||
return True
|
||||
return False
|
||||
|
|
@ -487,7 +538,7 @@ class BaseGraphQlQueryField(object):
|
|||
return self._path
|
||||
|
||||
def reset_cursor(self):
|
||||
for child in self._children:
|
||||
for child in self._children_iter():
|
||||
child.reset_cursor()
|
||||
|
||||
def get_variable_value(self, *args, **kwargs):
|
||||
|
|
@ -518,11 +569,13 @@ class BaseGraphQlQueryField(object):
|
|||
self._children.append(field)
|
||||
field.set_parent(self)
|
||||
|
||||
def add_field(self, name, has_edges=None):
|
||||
if has_edges:
|
||||
item = GraphQlQueryEdgeField(name, self)
|
||||
else:
|
||||
item = GraphQlQueryField(name, self)
|
||||
def add_field_with_edges(self, name):
|
||||
item = GraphQlQueryEdgeField(name, self)
|
||||
self.add_obj_field(item)
|
||||
return item
|
||||
|
||||
def add_field(self, name):
|
||||
item = GraphQlQueryField(name, self)
|
||||
self.add_obj_field(item)
|
||||
return item
|
||||
|
||||
|
|
@ -580,7 +633,7 @@ class BaseGraphQlQueryField(object):
|
|||
def _fake_children_parse(self):
|
||||
"""Mark children as they don't need query."""
|
||||
|
||||
for child in self._children:
|
||||
for child in self._children_iter():
|
||||
child.parse_result({}, {}, {})
|
||||
|
||||
@abstractmethod
|
||||
|
|
@ -673,12 +726,38 @@ class GraphQlQueryEdgeField(BaseGraphQlQueryField):
|
|||
def __init__(self, *args, **kwargs):
|
||||
super(GraphQlQueryEdgeField, self).__init__(*args, **kwargs)
|
||||
self._cursor = None
|
||||
self._edge_children = []
|
||||
|
||||
@property
|
||||
def child_indent(self):
|
||||
offset = self.offset * 2
|
||||
return self.indent + offset
|
||||
|
||||
def _children_iter(self):
|
||||
for child in super(GraphQlQueryEdgeField, self)._children_iter():
|
||||
yield child
|
||||
|
||||
for child in self._edge_children:
|
||||
yield child
|
||||
|
||||
def add_obj_field(self, field):
|
||||
if field in self._edge_children:
|
||||
return
|
||||
|
||||
super(GraphQlQueryEdgeField, self).add_obj_field(field)
|
||||
|
||||
def add_obj_edge_field(self, field):
|
||||
if field in self._edge_children or field in self._children:
|
||||
return
|
||||
|
||||
self._edge_children.append(field)
|
||||
field.set_parent(self)
|
||||
|
||||
def add_edge_field(self, name):
|
||||
item = GraphQlQueryField(name, self)
|
||||
self.add_obj_edge_field(item)
|
||||
return item
|
||||
|
||||
def reset_cursor(self):
|
||||
# Reset cursor only for edges
|
||||
self._cursor = None
|
||||
|
|
@ -733,6 +812,9 @@ class GraphQlQueryEdgeField(BaseGraphQlQueryField):
|
|||
nodes_by_cursor[edge_cursor] = edge_value
|
||||
node_values.append(edge_value)
|
||||
|
||||
for child in self._edge_children:
|
||||
child.parse_result(edge, edge_value, progress_data)
|
||||
|
||||
for child in self._children:
|
||||
child.parse_result(edge["node"], edge_value, progress_data)
|
||||
|
||||
|
|
@ -740,12 +822,12 @@ class GraphQlQueryEdgeField(BaseGraphQlQueryField):
|
|||
return
|
||||
|
||||
change_cursor = True
|
||||
for child in self._children:
|
||||
for child in self._children_iter():
|
||||
if child.need_query:
|
||||
change_cursor = False
|
||||
|
||||
if change_cursor:
|
||||
for child in self._children:
|
||||
for child in self._children_iter():
|
||||
child.reset_cursor()
|
||||
self._cursor = new_cursor
|
||||
|
||||
|
|
@ -761,7 +843,7 @@ class GraphQlQueryEdgeField(BaseGraphQlQueryField):
|
|||
return filters
|
||||
|
||||
def calculate_query(self):
|
||||
if not self._children:
|
||||
if not self._children and not self._edge_children:
|
||||
raise ValueError("Missing child definitions for edges {}".format(
|
||||
self.path
|
||||
))
|
||||
|
|
@ -779,16 +861,21 @@ class GraphQlQueryEdgeField(BaseGraphQlQueryField):
|
|||
edges_offset = offset + self.offset * " "
|
||||
node_offset = edges_offset + self.offset * " "
|
||||
output.append(edges_offset + "edges {")
|
||||
output.append(node_offset + "node {")
|
||||
for field in self._edge_children:
|
||||
output.append(field.calculate_query())
|
||||
|
||||
for field in self._children:
|
||||
output.append(
|
||||
field.calculate_query()
|
||||
)
|
||||
if self._children:
|
||||
output.append(node_offset + "node {")
|
||||
|
||||
for field in self._children:
|
||||
output.append(
|
||||
field.calculate_query()
|
||||
)
|
||||
|
||||
output.append(node_offset + "}")
|
||||
if self.child_has_edges:
|
||||
output.append(node_offset + "cursor")
|
||||
|
||||
output.append(node_offset + "}")
|
||||
if self.child_has_edges:
|
||||
output.append(node_offset + "cursor")
|
||||
output.append(edges_offset + "}")
|
||||
|
||||
# Add page information
|
||||
|
|
|
|||
|
|
@ -25,6 +25,58 @@ def fields_to_dict(fields):
|
|||
return output
|
||||
|
||||
|
||||
def add_links_fields(entity_field, nested_fields):
|
||||
if "links" not in nested_fields:
|
||||
return
|
||||
links_fields = nested_fields.pop("links")
|
||||
|
||||
link_edge_fields = {
|
||||
"id",
|
||||
"linkType",
|
||||
"projectName",
|
||||
"entityType",
|
||||
"entityId",
|
||||
"direction",
|
||||
"description",
|
||||
"author",
|
||||
}
|
||||
if isinstance(links_fields, dict):
|
||||
simple_fields = set(links_fields)
|
||||
simple_variant = len(simple_fields - link_edge_fields) == 0
|
||||
else:
|
||||
simple_variant = True
|
||||
simple_fields = link_edge_fields
|
||||
|
||||
link_field = entity_field.add_field_with_edges("links")
|
||||
|
||||
link_type_var = link_field.add_variable("linkTypes", "[String!]")
|
||||
link_dir_var = link_field.add_variable("linkDirection", "String!")
|
||||
link_field.set_filter("linkTypes", link_type_var)
|
||||
link_field.set_filter("direction", link_dir_var)
|
||||
|
||||
if simple_variant:
|
||||
for key in simple_fields:
|
||||
link_field.add_edge_field(key)
|
||||
return
|
||||
|
||||
query_queue = collections.deque()
|
||||
for key, value in links_fields.items():
|
||||
if key in link_edge_fields:
|
||||
link_field.add_edge_field(key)
|
||||
continue
|
||||
query_queue.append((key, value, link_field))
|
||||
|
||||
while query_queue:
|
||||
item = query_queue.popleft()
|
||||
key, value, parent = item
|
||||
field = parent.add_field(key)
|
||||
if value is FIELD_VALUE:
|
||||
continue
|
||||
|
||||
for k, v in value.items():
|
||||
query_queue.append((k, v, field))
|
||||
|
||||
|
||||
def project_graphql_query(fields):
|
||||
query = GraphQlQuery("ProjectQuery")
|
||||
project_name_var = query.add_variable("projectName", "String!")
|
||||
|
|
@ -51,7 +103,7 @@ def project_graphql_query(fields):
|
|||
|
||||
def projects_graphql_query(fields):
|
||||
query = GraphQlQuery("ProjectsQuery")
|
||||
projects_field = query.add_field("projects", has_edges=True)
|
||||
projects_field = query.add_field_with_edges("projects")
|
||||
|
||||
nested_fields = fields_to_dict(fields)
|
||||
|
||||
|
|
@ -83,7 +135,7 @@ def folders_graphql_query(fields):
|
|||
project_field = query.add_field("project")
|
||||
project_field.set_filter("name", project_name_var)
|
||||
|
||||
folders_field = project_field.add_field("folders", has_edges=True)
|
||||
folders_field = project_field.add_field_with_edges("folders")
|
||||
folders_field.set_filter("ids", folder_ids_var)
|
||||
folders_field.set_filter("parentIds", parent_folder_ids_var)
|
||||
folders_field.set_filter("names", folder_names_var)
|
||||
|
|
@ -91,6 +143,7 @@ def folders_graphql_query(fields):
|
|||
folders_field.set_filter("hasSubsets", has_subsets_var)
|
||||
|
||||
nested_fields = fields_to_dict(fields)
|
||||
add_links_fields(folders_field, nested_fields)
|
||||
|
||||
query_queue = collections.deque()
|
||||
for key, value in nested_fields.items():
|
||||
|
|
@ -119,7 +172,7 @@ def tasks_graphql_query(fields):
|
|||
project_field = query.add_field("project")
|
||||
project_field.set_filter("name", project_name_var)
|
||||
|
||||
tasks_field = project_field.add_field("tasks", has_edges=True)
|
||||
tasks_field = project_field.add_field_with_edges("tasks")
|
||||
tasks_field.set_filter("ids", task_ids_var)
|
||||
# WARNING: At moment when this been created 'names' filter is not supported
|
||||
tasks_field.set_filter("names", task_names_var)
|
||||
|
|
@ -127,6 +180,7 @@ def tasks_graphql_query(fields):
|
|||
tasks_field.set_filter("folderIds", folder_ids_var)
|
||||
|
||||
nested_fields = fields_to_dict(fields)
|
||||
add_links_fields(tasks_field, nested_fields)
|
||||
|
||||
query_queue = collections.deque()
|
||||
for key, value in nested_fields.items():
|
||||
|
|
@ -155,12 +209,13 @@ def subsets_graphql_query(fields):
|
|||
project_field = query.add_field("project")
|
||||
project_field.set_filter("name", project_name_var)
|
||||
|
||||
subsets_field = project_field.add_field("subsets", has_edges=True)
|
||||
subsets_field = project_field.add_field_with_edges("subsets")
|
||||
subsets_field.set_filter("ids", subset_ids_var)
|
||||
subsets_field.set_filter("names", subset_names_var)
|
||||
subsets_field.set_filter("folderIds", folder_ids_var)
|
||||
|
||||
nested_fields = fields_to_dict(set(fields))
|
||||
add_links_fields(subsets_field, nested_fields)
|
||||
|
||||
query_queue = collections.deque()
|
||||
for key, value in nested_fields.items():
|
||||
|
|
@ -194,7 +249,7 @@ def versions_graphql_query(fields):
|
|||
project_field = query.add_field("project")
|
||||
project_field.set_filter("name", project_name_var)
|
||||
|
||||
subsets_field = project_field.add_field("versions", has_edges=True)
|
||||
subsets_field = project_field.add_field_with_edges("versions")
|
||||
subsets_field.set_filter("ids", version_ids_var)
|
||||
subsets_field.set_filter("subsetIds", subset_ids_var)
|
||||
subsets_field.set_filter("versions", versions_var)
|
||||
|
|
@ -203,6 +258,7 @@ def versions_graphql_query(fields):
|
|||
subsets_field.set_filter("heroOrLatestOnly", hero_or_latest_only_var)
|
||||
|
||||
nested_fields = fields_to_dict(set(fields))
|
||||
add_links_fields(subsets_field, nested_fields)
|
||||
|
||||
query_queue = collections.deque()
|
||||
for key, value in nested_fields.items():
|
||||
|
|
@ -231,12 +287,13 @@ def representations_graphql_query(fields):
|
|||
project_field = query.add_field("project")
|
||||
project_field.set_filter("name", project_name_var)
|
||||
|
||||
repres_field = project_field.add_field("representations", has_edges=True)
|
||||
repres_field = project_field.add_field_with_edges("representations")
|
||||
repres_field.set_filter("ids", repre_ids_var)
|
||||
repres_field.set_filter("versionIds", version_ids_var)
|
||||
repres_field.set_filter("names", repre_names_var)
|
||||
|
||||
nested_fields = fields_to_dict(set(fields))
|
||||
add_links_fields(repres_field, nested_fields)
|
||||
|
||||
query_queue = collections.deque()
|
||||
for key, value in nested_fields.items():
|
||||
|
|
@ -266,7 +323,7 @@ def representations_parents_qraphql_query(
|
|||
project_field = query.add_field("project")
|
||||
project_field.set_filter("name", project_name_var)
|
||||
|
||||
repres_field = project_field.add_field("representations", has_edges=True)
|
||||
repres_field = project_field.add_field_with_edges("representations")
|
||||
repres_field.add_field("id")
|
||||
repres_field.set_filter("ids", repre_ids_var)
|
||||
version_field = repres_field.add_field("version")
|
||||
|
|
@ -306,12 +363,13 @@ def workfiles_info_graphql_query(fields):
|
|||
project_field = query.add_field("project")
|
||||
project_field.set_filter("name", project_name_var)
|
||||
|
||||
workfiles_field = project_field.add_field("workfiles", has_edges=True)
|
||||
workfiles_field = project_field.add_field_with_edges("workfiles")
|
||||
workfiles_field.set_filter("ids", workfiles_info_ids)
|
||||
workfiles_field.set_filter("taskIds", task_ids_var)
|
||||
workfiles_field.set_filter("paths", paths_var)
|
||||
|
||||
nested_fields = fields_to_dict(set(fields))
|
||||
add_links_fields(workfiles_field, nested_fields)
|
||||
|
||||
query_queue = collections.deque()
|
||||
for key, value in nested_fields.items():
|
||||
|
|
@ -337,7 +395,7 @@ def events_graphql_query(fields):
|
|||
users_var = query.add_variable("eventUsers", "[String!]")
|
||||
include_logs_var = query.add_variable("includeLogsFilter", "Boolean!")
|
||||
|
||||
events_field = query.add_field("events", has_edges=True)
|
||||
events_field = query.add_field_with_edges("events")
|
||||
events_field.set_filter("topics", topics_var)
|
||||
events_field.set_filter("projects", projects_var)
|
||||
events_field.set_filter("states", states_var)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import copy
|
||||
import collections
|
||||
import uuid
|
||||
from abc import ABCMeta, abstractproperty
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
import six
|
||||
|
||||
|
|
@ -301,7 +301,8 @@ class AbstractOperation(object):
|
|||
def entity_type(self):
|
||||
return self._entity_type
|
||||
|
||||
@abstractproperty
|
||||
@property
|
||||
@abstractmethod
|
||||
def operation_name(self):
|
||||
"""Stringified type of operation."""
|
||||
|
||||
|
|
|
|||
1011
openpype/vendor/python/common/ayon_api/server_api.py
vendored
1011
openpype/vendor/python/common/ayon_api/server_api.py
vendored
File diff suppressed because it is too large
Load diff
|
|
@ -1,2 +1,2 @@
|
|||
"""Package declaring Python API for Ayon server."""
|
||||
__version__ = "0.1.16"
|
||||
__version__ = "0.1.17"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue