updated ayon api to '0.2.1'

This commit is contained in:
Jakub Trllo 2023-06-13 11:34:45 +02:00
parent b44ef67050
commit 706469205c
5 changed files with 802 additions and 56 deletions

View file

@ -59,13 +59,31 @@ from ._api import (
get_addon_url,
download_addon_private_file,
get_installers,
create_installer,
update_installer,
delete_installer,
download_installer,
upload_installer,
get_dependencies_info,
update_dependency_info,
get_dependency_packages,
create_dependency_package,
update_dependency_package,
delete_dependency_package,
download_dependency_package,
upload_dependency_package,
delete_dependency_package,
get_bundles,
create_bundle,
update_bundle,
delete_bundle,
get_info,
get_server_version,
get_server_version_tuple,
get_user,
get_users,
@ -87,9 +105,11 @@ from ._api import (
get_addons_project_settings,
get_addons_settings,
get_project_names,
get_projects,
get_project,
create_project,
update_project,
delete_project,
get_folder_by_id,
@ -218,13 +238,31 @@ __all__ = (
"get_addon_url",
"download_addon_private_file",
"get_installers",
"create_installer",
"update_installer",
"delete_installer",
"download_installer",
"upload_installer",
"get_dependencies_info",
"update_dependency_info",
"get_dependency_packages",
"create_dependency_package",
"update_dependency_package",
"delete_dependency_package",
"download_dependency_package",
"upload_dependency_package",
"delete_dependency_package",
"get_bundles",
"create_bundle",
"update_bundle",
"delete_bundle",
"get_info",
"get_server_version",
"get_server_version_tuple",
"get_user",
"get_users",
@ -245,9 +283,11 @@ __all__ = (
"get_addons_project_settings",
"get_addons_settings",
"get_project_names",
"get_projects",
"get_project",
"create_project",
"update_project",
"delete_project",
"get_folder_by_id",

View file

@ -531,6 +531,53 @@ def download_addon_private_file(*args, **kwargs):
return con.download_addon_private_file(*args, **kwargs)
def get_info(*args, **kwargs):
con = get_server_api_connection()
return con.get_info(*args, **kwargs)
def get_server_version(*args, **kwargs):
con = get_server_api_connection()
return con.get_server_version(*args, **kwargs)
def get_server_version_tuple(*args, **kwargs):
con = get_server_api_connection()
return con.get_server_version_tuple(*args, **kwargs)
# Installers
def get_installers(*args, **kwargs):
con = get_server_api_connection()
return con.get_installers(*args, **kwargs)
def create_installer(*args, **kwargs):
con = get_server_api_connection()
return con.create_installer(*args, **kwargs)
def update_installer(*args, **kwargs):
con = get_server_api_connection()
return con.update_installer(*args, **kwargs)
def delete_installer(*args, **kwargs):
con = get_server_api_connection()
return con.delete_installer(*args, **kwargs)
def download_installer(*args, **kwargs):
con = get_server_api_connection()
con.download_installer(*args, **kwargs)
def upload_installer(*args, **kwargs):
con = get_server_api_connection()
con.upload_installer(*args, **kwargs)
# Dependency packages
def get_dependencies_info(*args, **kwargs):
con = get_server_api_connection()
return con.get_dependencies_info(*args, **kwargs)
@ -551,6 +598,21 @@ def upload_dependency_package(*args, **kwargs):
return con.upload_dependency_package(*args, **kwargs)
def get_dependency_packages(*args, **kwargs):
con = get_server_api_connection()
return con.get_dependency_packages(*args, **kwargs)
def create_dependency_package(*args, **kwargs):
con = get_server_api_connection()
return con.create_dependency_package(*args, **kwargs)
def update_dependency_package(*args, **kwargs):
con = get_server_api_connection()
return con.update_dependency_package(*args, **kwargs)
def delete_dependency_package(*args, **kwargs):
con = get_server_api_connection()
return con.delete_dependency_package(*args, **kwargs)
@ -561,6 +623,26 @@ def get_project_anatomy_presets(*args, **kwargs):
return con.get_project_anatomy_presets(*args, **kwargs)
def get_bundles(*args, **kwargs):
con = get_server_api_connection()
return con.get_bundles(*args, **kwargs)
def create_bundle(*args, **kwargs):
con = get_server_api_connection()
return con.create_bundle(*args, **kwargs)
def update_bundle(*args, **kwargs):
con = get_server_api_connection()
return con.update_bundle(*args, **kwargs)
def delete_bundle(*args, **kwargs):
con = get_server_api_connection()
return con.delete_bundle(*args, **kwargs)
def get_project_anatomy_preset(*args, **kwargs):
con = get_server_api_connection()
return con.get_project_anatomy_preset(*args, **kwargs)
@ -621,6 +703,11 @@ def get_addons_settings(*args, **kwargs):
return con.get_addons_settings(*args, **kwargs)
def get_project_names(*args, **kwargs):
con = get_server_api_connection()
return con.get_project_names(*args, **kwargs)
def get_project(*args, **kwargs):
con = get_server_api_connection()
return con.get_project(*args, **kwargs)
@ -801,6 +888,11 @@ def create_project(
)
def update_project(project_name, *args, **kwargs):
con = get_server_api_connection()
return con.update_project(project_name, *args, **kwargs)
def delete_project(project_name):
con = get_server_api_connection()
return con.delete_project(project_name)

View file

@ -683,6 +683,82 @@ class EntityHub(object):
"entityId": entity.id
}
def _pre_commit_types_changes(
self, project_changes, orig_types, changes_key, post_changes
):
"""Compare changes of types on a project.
Compare old and new types. Change project changes content if some old
types were removed. In that case the final change of types will
happen when all other entities have changed.
Args:
project_changes (dict[str, Any]): Project changes.
orig_types (list[dict[str, Any]]): Original types.
changes_key (Literal[folderTypes, taskTypes]): Key of type changes
in project changes.
post_changes (dict[str, Any]): An object where post changes will
be stored.
"""
if changes_key not in project_changes:
return
new_types = project_changes[changes_key]
orig_types_by_name = {
type_info["name"]: type_info
for type_info in orig_types
}
new_names = {
type_info["name"]
for type_info in new_types
}
diff_names = set(orig_types_by_name) - new_names
if not diff_names:
return
# Create copy of folder type changes to post changes
# - post changes will be commited at the end
post_changes[changes_key] = copy.deepcopy(new_types)
for type_name in diff_names:
new_types.append(orig_types_by_name[type_name])
def _pre_commit_project(self):
"""Some project changes cannot be committed before hierarchy changes.
It is not possible to change folder types or task types if there are
existing hierarchy items using the removed types. For that purposes
is first committed union of all old and new types and post changes
are prepared when all existing entities are changed.
Returns:
dict[str, Any]: Changes that will be committed after hierarchy
changes.
"""
project_changes = self.project_entity.changes
post_changes = {}
if not project_changes:
return post_changes
self._pre_commit_types_changes(
project_changes,
self.project_entity.get_orig_folder_types(),
"folderType",
post_changes
)
self._pre_commit_types_changes(
project_changes,
self.project_entity.get_orig_task_types(),
"taskType",
post_changes
)
self._connection.update_project(self.project_name, **project_changes)
return post_changes
def commit_changes(self):
"""Commit any changes that happened on entities.
@ -690,6 +766,9 @@ class EntityHub(object):
Use Operations Session instead of known operations body.
"""
post_project_changes = self._pre_commit_project()
self.project_entity.lock()
project_changes = self.project_entity.changes
if project_changes:
response = self._connection.patch(
@ -760,6 +839,9 @@ class EntityHub(object):
self._connection.send_batch_operations(
self.project_name, operations_body
)
if post_project_changes:
self._connection.update_project(
self.project_name, **post_project_changes)
self.lock()
@ -1463,6 +1545,9 @@ class ProjectEntity(BaseEntity):
parent = property(get_parent, set_parent)
def get_orig_folder_types(self):
return copy.deepcopy(self._orig_folder_types)
def get_folder_types(self):
return copy.deepcopy(self._folder_types)
@ -1474,6 +1559,9 @@ class ProjectEntity(BaseEntity):
new_folder_types.append(folder_type)
self._folder_types = new_folder_types
def get_orig_task_types(self):
return copy.deepcopy(self._orig_task_types)
def get_task_types(self):
return copy.deepcopy(self._task_types)

View file

@ -4,6 +4,7 @@ import io
import json
import logging
import collections
import datetime
import platform
import copy
import uuid
@ -70,6 +71,14 @@ PROJECT_NAME_REGEX = re.compile(
"^[{}]+$".format(PROJECT_NAME_ALLOWED_SYMBOLS)
)
VERSION_REGEX = re.compile(
r"(?P<major>0|[1-9]\d*)"
r"\.(?P<minor>0|[1-9]\d*)"
r"\.(?P<patch>0|[1-9]\d*)"
r"(?:-(?P<prerelease>[a-zA-Z\d\-.]*))?"
r"(?:\+(?P<buildmetadata>[a-zA-Z\d\-.]*))?"
)
def _get_description(response):
if HTTPStatus is None:
@ -329,6 +338,8 @@ class ServerAPI(object):
self._access_token_is_service = None
self._token_is_valid = None
self._server_available = None
self._server_version = None
self._server_version_tuple = None
self._session = None
@ -631,12 +642,52 @@ class ServerAPI(object):
Use this method for validation of token instead of 'get_user'.
Returns:
Dict[str, Any]: Information from server.
dict[str, Any]: Information from server.
"""
response = self.get("info")
return response.data
def get_server_version(self):
"""Get server version.
Version should match semantic version (https://semver.org/).
Returns:
str: Server version.
"""
if self._server_version is None:
self._server_version = self.get_info()["version"]
return self._server_version
def get_server_version_tuple(self):
"""Get server version as tuple.
Version should match semantic version (https://semver.org/).
This function only returns first three numbers of version.
Returns:
Tuple[int, int, int, Union[str, None], Union[str, None]]: Server
version.
"""
if self._server_version_tuple is None:
re_match = VERSION_REGEX.fullmatch(
self.get_server_version())
self._server_version_tuple = (
int(re_match.group("major")),
int(re_match.group("minor")),
int(re_match.group("patch")),
re_match.group("prerelease"),
re_match.group("buildmetadata")
)
return self._server_version_tuple
server_version = property(get_server_version)
server_version_tuple = property(get_server_version_tuple)
def _get_user_info(self):
if self._access_token is None:
return None
@ -869,7 +920,7 @@ class ServerAPI(object):
event_id (str): Id of event.
Returns:
Dict[str, Any]: Full event data.
dict[str, Any]: Full event data.
"""
response = self.get("events/{}".format(event_id))
@ -902,7 +953,7 @@ class ServerAPI(object):
for each event.
Returns:
Generator[Dict[str, Any]]: Available events matching filters.
Generator[dict[str, Any]]: Available events matching filters.
"""
filters = {}
@ -1269,7 +1320,7 @@ class ServerAPI(object):
Cache schema - How to find out it is outdated?
Returns:
Dict[str, Any]: Full server schema.
dict[str, Any]: Full server schema.
"""
url = "{}/openapi.json".format(self._base_url)
@ -1287,7 +1338,7 @@ class ServerAPI(object):
e.g. 'config' has just object definition without reference schema.
Returns:
Dict[str, Any]: Component schemas.
dict[str, Any]: Component schemas.
"""
server_schema = self.get_server_schema()
@ -1395,7 +1446,7 @@ class ServerAPI(object):
received.
Returns:
Dict[str, Dict[str, Any]]: Attribute schemas that are available
dict[str, dict[str, Any]]: Attribute schemas that are available
for entered entity type.
"""
attributes = self._entity_type_attributes_cache.get(entity_type)
@ -1563,6 +1614,148 @@ class ServerAPI(object):
)
return dst_filepath
def get_installers(self, version=None, platform_name=None):
"""Information about desktop application installers on server.
Desktop application installers are helpers to download/update AYON
desktop application for artists.
Args:
version (Optional[str]): Filter installers by version.
platform_name (Optional[str]): Filter installers by platform name.
Returns:
list[dict[str, Any]]:
"""
query_fields = [
"{}={}".format(key, value)
for key, value in (
("version", version),
("platform", platform_name),
)
if value
]
query = ""
if query_fields:
query = "?{}".format(",".join(query_fields))
response = self.get("desktop/installers{}".format(query))
response.raise_for_status()
return response.data
def create_installer(
self,
filename,
version,
python_version,
platform_name,
python_modules,
checksum,
checksum_type,
file_size,
sources=None,
):
"""Create new installer information on server.
This step will create only metadata. Make sure to upload installer
to the server using 'upload_installer' method.
Args:
filename (str): Installer filename.
version (str): Version of installer.
python_version (str): Version of Python.
platform_name (str): Name of platform.
python_modules (dict[str, str]): Python modules that are available
in installer.
checksum (str): Installer file checksum.
checksum_type (str): Type of checksum used to create checksum.
file_size (int): File size.
sources (Optional[list[dict[str, Any]]]): List of sources that
can be used to download file.
"""
body = {
"filename": filename,
"version": version,
"pythonVersion": python_version,
"platform": platform_name,
"pythonModules": python_modules,
"checksum": checksum,
"checksumType": checksum_type,
"size": file_size,
}
if sources:
body["sources"] = sources
response = self.post("desktop/installers", **body)
response.raise_for_status()
def update_installer(self, filename, sources):
"""Update installer information on server.
Args:
filename (str): Installer filename.
sources (list[dict[str, Any]]): List of sources that
can be used to download file. Fully replaces existing sources.
"""
response = self.post(
"desktop/installers/{}".format(filename),
sources=sources
)
response.raise_for_status()
def delete_installer(self, filename):
"""Delete installer from server.
Args:
filename (str): Installer filename.
"""
response = self.delete("dekstop/installers/{}".format(filename))
response.raise_for_status()
def download_installer(
self,
filename,
dst_filepath,
chunk_size=None,
progress=None
):
"""Download installer file from server.
Args:
filename (str): Installer filename.
dst_filepath (str): Destination filepath.
chunk_size (Optional[int]): Download chunk size.
progress (Optional[TransferProgress]): Object that gives ability
to track download progress.
"""
self.download_file(
"desktop/installers/{}".format(filename),
dst_filepath,
chunk_size=chunk_size,
progress=progress
)
def upload_installer(self, src_filepath, dst_filename, progress=None):
"""Upload installer file to server.
Args:
src_filepath (str): Source filepath.
dst_filename (str): Destination filename.
progress (Optional[TransferProgress]): Object that gives ability
to track download progress.
"""
self.upload_file(
"desktop/installers/{}".format(dst_filename),
src_filepath,
progress=progress
)
def get_dependencies_info(self):
"""Information about dependency packages on server.
@ -1581,13 +1774,22 @@ class ServerAPI(object):
"productionPackage": str
}
Deprecated:
Deprecated since server version 0.2.1. Use
'get_dependency_packages' instead.
Returns:
dict[str, Any]: Information about dependency packages known for
server.
"""
result = self.get("dependencies")
return result.data
major, minor, patch, _, _ = self.server_version_tuple
if major == 0 and (minor < 2 or (minor == 2 and patch < 1)):
result = self.get("dependencies")
return result.data
packages = self.get_dependency_packages()
packages["productionPackage"] = None
return packages
def update_dependency_info(
self,
@ -1604,21 +1806,26 @@ class ServerAPI(object):
The endpoint can be used to create or update dependency package.
Deprecated:
Deprecated for server version 0.2.1. Use
'create_dependency_pacakge' instead.
Args:
name (str): Name of dependency package.
platform_name (Literal["windows", "linux", "darwin"]): Platform for
which is dependency package targeted.
platform_name (Literal["windows", "linux", "darwin"]): Platform
for which is dependency package targeted.
size (int): Size of dependency package in bytes.
checksum (str): Checksum of archive file where dependencies are.
checksum_algorithm (Optional[str]): Algorithm used to calculate
checksum. By default, is used 'md5' (defined by server).
supported_addons (Optional[Dict[str, str]]): Name of addons for
supported_addons (Optional[dict[str, str]]): Name of addons for
which was the package created.
'{"<addon name>": "<addon version>", ...}'
python_modules (Optional[Dict[str, str]]): Python modules in
python_modules (Optional[dict[str, str]]): Python modules in
dependencies package.
'{"<module name>": "<module version>", ...}'
sources (Optional[List[Dict[str, Any]]]): Information about
sources (Optional[list[dict[str, Any]]]): Information about
sources where dependency package is available.
"""
@ -1645,27 +1852,153 @@ class ServerAPI(object):
raise ServerError("Failed to create/update dependency")
return response.data
def get_dependency_packages(self):
"""Information about dependency packages on server.
To download dependency package, use 'download_dependency_package'
method and pass in 'filename'.
Example data structure:
{
"packages": [
{
"filename": str,
"platform": str,
"checksum": str,
"checksumAlgorithm": str,
"size": int,
"sources": list[dict[str, Any]],
"supportedAddons": dict[str, str],
"pythonModules": dict[str, str]
}
]
}
Returns:
dict[str, Any]: Information about dependency packages known for
server.
"""
result = self.get("desktop/dependency_packages")
result.raise_for_status()
return result.data
def create_dependency_package(
self,
filename,
python_modules,
source_addons,
installer_version,
checksum,
checksum_algorithm,
file_size,
sources=None,
platform_name=None,
):
"""Create dependency package on server.
The package will be created on a server, it is also required to upload
the package archive file (using 'upload_dependency_package').
Args:
filename (str): Filename of dependency package.
python_modules (dict[str, str]): Python modules in dependency
package.
'{"<module name>": "<module version>", ...}'
source_addons (dict[str, str]): Name of addons for which is
dependency package created.
'{"<addon name>": "<addon version>", ...}'
installer_version (str): Version of installer for which was
package created.
checksum (str): Checksum of archive file where dependencies are.
checksum_algorithm (str): Algorithm used to calculate checksum.
file_size (Optional[int]): Size of file.
sources (Optional[list[dict[str, Any]]]): Information about
sources from where it is possible to get file.
platform_name (Optional[str]): Name of platform for which is
dependency package targeted. Default value is
current platform.
"""
post_body = {
"filename": filename,
"pythonModules": python_modules,
"sourceAddons": source_addons,
"installerVersion": installer_version,
"checksum": checksum,
"checksumAlgorithm": checksum_algorithm,
"size": file_size,
"platform": platform_name or platform.system().lower(),
}
if sources:
post_body["sources"] = sources
response = self.post("desktop/dependency_packages", **post_body)
response.raise_for_status()
def update_dependency_package(self, filename, sources):
"""Update dependency package metadata on server.
Args:
filename (str): Filename of dependency package.
sources (list[dict[str, Any]]): Information about
sources from where it is possible to get file. Fully replaces
existing sources.
"""
response = self.patch(
"desktop/dependency_packages/{}".format(filename),
sources=sources
)
response.raise_for_status()
def delete_dependency_package(self, filename, platform_name=None):
"""Remove dependency package for specific platform.
Args:
filename (str): Filename of dependency package. Or name of package
for server version 0.2.0 or lower.
platform_name (Optional[str]): Which platform of the package
should be removed. Current platform is used if not passed.
Deprecated since version 0.2.1
"""
major, minor, patch, _, _ = self.server_version_tuple
if major == 0 and (minor < 2 or (minor == 2 and patch < 1)):
if platform_name is None:
platform_name = platform.system().lower()
url = "dependencies/{}/{}".format(filename, platform_name)
else:
url = "desktop/dependency_packages/{}".format(filename)
response = self.delete(url)
if response.status != 200:
raise ServerError("Failed to delete dependency file")
return response.data
def download_dependency_package(
self,
package_name,
src_filename,
dst_directory,
filename,
dst_filename,
platform_name=None,
chunk_size=None,
progress=None,
):
"""Download dependency package from server.
This method requires to have authorized token available. The package is
only downloaded.
This method requires to have authorized token available. The package
is only downloaded.
Args:
package_name (str): Name of package to download.
src_filename (str): Filename of dependency pacakge.
For server version 0.2.0 and lower it is name of package
to download.
dst_directory (str): Where the file should be downloaded.
filename (str): Name of destination filename.
dst_filename (str): Name of destination filename.
platform_name (Optional[str]): Name of platform for which the
dependency package is targeted. Default value is
current platform.
current platform. Deprecated since server version 0.2.1.
chunk_size (Optional[int]): Download chunk size.
progress (Optional[TransferProgress]): Object that gives ability
to track download progress.
@ -1673,12 +2006,18 @@ class ServerAPI(object):
Returns:
str: Filepath to downloaded file.
"""
if platform_name is None:
platform_name = platform.system().lower()
package_filepath = os.path.join(dst_directory, filename)
major, minor, patch, _, _ = self.server_version_tuple
if major == 0 and (minor < 2 or (minor == 2 and patch < 1)):
if platform_name is None:
platform_name = platform.system().lower()
url = "dependencies/{}/{}".format(src_filename, platform_name)
else:
url = "desktop/dependency_packages/{}".format(src_filename)
package_filepath = os.path.join(dst_directory, dst_filename)
self.download_file(
"dependencies/{}/{}".format(package_name, platform_name),
url,
package_filepath,
chunk_size=chunk_size,
progress=progress
@ -1686,47 +2025,170 @@ class ServerAPI(object):
return package_filepath
def upload_dependency_package(
self, filepath, package_name, platform_name=None, progress=None
self, src_filepath, dst_filename, platform_name=None, progress=None
):
"""Upload dependency package to server.
Args:
filepath (str): Path to a package file.
package_name (str): Name of package. Must be unique.
src_filepath (str): Path to a package file.
dst_filename (str): Dependency package filename or name of package
for server version 0.2.0 or lower. Must be unique.
platform_name (Optional[str]): For which platform is the
package targeted.
package targeted. Deprecated since server version 0.2.1.
progress (Optional[TransferProgress]): Object to keep track about
upload state.
"""
if platform_name is None:
platform_name = platform.system().lower()
major, minor, patch, _, _ = self.server_version_tuple
if major == 0 and (minor < 2 or (minor == 2 and patch < 1)):
if platform_name is None:
platform_name = platform.system().lower()
url = "dependencies/{}/{}".format(dst_filename, platform_name)
else:
url = "desktop/dependency_packages/{}".format(dst_filename)
self.upload_file(
"dependencies/{}/{}".format(package_name, platform_name),
filepath,
progress=progress
)
self.upload_file(url, src_filepath, progress=progress)
def delete_dependency_package(self, package_name, platform_name=None):
"""Remove dependency package for specific platform.
def create_dependency_package_basename(self, platform_name=None):
"""Create basename for dependency package file.
Args:
package_name (str): Name of package to remove.
platform_name (Optional[str]): Which platform of the package
should be removed. Current platform is used if not passed.
platform_name (Optional[str]): Name of platform for which the
bundle is targeted. Default value is current platform.
Returns:
str: Dependency package name with timestamp and platform.
"""
if platform_name is None:
platform_name = platform.system().lower()
response = self.delete(
"dependencies/{}/{}".format(package_name, platform_name),
)
if response.status != 200:
raise ServerError("Failed to delete dependency file")
now_date = datetime.datetime.now()
time_stamp = now_date.strftime("%y%m%d%H%M")
return "ayon_{}_{}".format(time_stamp, platform_name)
def get_bundles(self):
"""Server bundles with basic information.
Example output:
{
"bundles": [
{
"name": "my_bundle",
"createdAt": "2023-06-12T15:37:02.420260",
"installerVersion": "1.0.0",
"addons": {
"core": "1.2.3"
},
"dependencyPackages": {
"windows": "a_windows_package123.zip",
"linux": "a_linux_package123.zip",
"darwin": "a_mac_package123.zip"
},
"isProduction": False,
"isStaging": False
}
],
"productionBundle": "my_bundle",
"stagingBundle": "test_bundle"
}
Returns:
dict[str, Any]: Server bundles with basic information.
"""
response = self.get("desktop/bundles")
response.raise_for_status()
return response.data
def create_bundle(
self,
name,
addon_versions,
installer_version,
dependency_packages=None,
is_production=None,
is_staging=None
):
"""Create bundle on server.
Bundle cannot be changed once is created. Only isProduction, isStaging
and dependency packages can change after creation.
Args:
name (str): Name of bundle.
addon_versions (dict[str, str]): Addon versions.
installer_version (Union[str, None]): Installer version.
dependency_packages (Optional[dict[str, str]]): Dependency
package names. Keys are platform names and values are name of
packages.
is_production (Optional[bool]): Bundle will be marked as
production.
is_staging (Optional[bool]): Bundle will be marked as staging.
"""
body = {
"name": name,
"installerVersion": installer_version,
"addons": addon_versions,
}
for key, value in (
("dependencyPackages", dependency_packages),
("isProduction", is_production),
("isStaging", is_staging),
):
if value is not None:
body[key] = value
response = self.post("desktop/bundles", **body)
response.raise_for_status()
def update_bundle(
self,
bundle_name,
dependency_packages=None,
is_production=None,
is_staging=None
):
"""Update bundle on server.
Dependency packages can be update only for single platform. Others
will be left untouched. Use 'None' value to unset dependency package
from bundle.
Args:
bundle_name (str): Name of bundle.
dependency_packages (Optional[dict[str, str]]): Dependency pacakge
names that should be used with the bundle.
is_production (Optional[bool]): Bundle will be marked as
production.
is_staging (Optional[bool]): Bundle will be marked as staging.
"""
body = {
key: value
for key, value in (
("dependencyPackages", dependency_packages),
("isProduction", is_production),
("isStaging", is_staging),
)
if value is not None
}
response = self.patch(
"desktop/bundles/{}".format(bundle_name), **body
)
response.raise_for_status()
def delete_bundle(self, bundle_name):
"""Delete bundle from server.
Args:
bundle_name (str): Name of bundle to delete.
"""
response = self.delete("desktop/bundles/{}".format(bundle_name))
response.raise_for_status()
# Anatomy presets
def get_project_anatomy_presets(self):
"""Anatomy presets available on server.
@ -2150,7 +2612,7 @@ class ServerAPI(object):
project_name (str): Name of project.
Returns:
Union[Dict[str, Any], None]: Project entity data or 'None' if
Union[dict[str, Any], None]: Project entity data or 'None' if
project was not found.
"""
@ -2174,7 +2636,7 @@ class ServerAPI(object):
are returned if 'None' is passed.
Returns:
Generator[Dict[str, Any]]: Available projects.
Generator[dict[str, Any]]: Available projects.
"""
for project_name in self.get_project_names(active, library):
@ -2235,7 +2697,7 @@ class ServerAPI(object):
are returned if 'None' is passed.
Returns:
List[str]: List of available project names.
list[str]: List of available project names.
"""
query_keys = {}
@ -2276,7 +2738,7 @@ class ServerAPI(object):
not explicitly set on entity will have 'None' value.
Returns:
Generator[Dict[str, Any]]: Queried projects.
Generator[dict[str, Any]]: Queried projects.
"""
if fields is None:
@ -2316,7 +2778,7 @@ class ServerAPI(object):
not explicitly set on entity will have 'None' value.
Returns:
Union[Dict[str, Any], None]: Project entity data or None
Union[dict[str, Any], None]: Project entity data or None
if project was not found.
"""
@ -3112,7 +3574,7 @@ class ServerAPI(object):
not explicitly set on entity will have 'None' value.
Returns:
Generator[Dict[str, Any]]: Queried version entities.
Generator[dict[str, Any]]: Queried version entities.
"""
if not fields:
@ -3570,7 +4032,7 @@ class ServerAPI(object):
not explicitly set on entity will have 'None' value.
Returns:
Generator[Dict[str, Any]]: Queried representation entities.
Generator[dict[str, Any]]: Queried representation entities.
"""
if not fields:
@ -4253,7 +4715,7 @@ class ServerAPI(object):
ValueError: When project name already exists.
Returns:
Dict[str, Any]: Created project entity.
dict[str, Any]: Created project entity.
"""
if self.get_project(project_name):
@ -4286,6 +4748,70 @@ class ServerAPI(object):
return self.get_project(project_name)
def update_project(
self,
project_name,
library=None,
folder_types=None,
task_types=None,
link_types=None,
statuses=None,
tags=None,
config=None,
attrib=None,
data=None,
active=None,
project_code=None,
**changes
):
"""Update project entity on server.
Args:
project_name (str): Name of project.
library (Optional[bool]): Change library state.
folder_types (Optional[list[dict[str, Any]]]): Folder type
definitions.
task_types (Optional[list[dict[str, Any]]]): Task type
definitions.
link_types (Optional[list[dict[str, Any]]]): Link type
definitions.
statuses (Optional[list[dict[str, Any]]]): Status definitions.
tags (Optional[list[dict[str, Any]]]): List of tags available to
set on entities.
config (Optional[dict[dict[str, Any]]]): Project anatomy config
with templates and roots.
attrib (Optional[dict[str, Any]]): Project attributes to change.
data (Optional[dict[str, Any]]): Custom data of a project. This
value will 100% override project data.
active (Optional[bool]): Change active state of a project.
project_code (Optional[str]): Change project code. Not recommended
during production.
**changes: Other changed keys based on Rest API documentation.
"""
changes.update({
key: value
for key, value in (
("library", library),
("folderTypes", folder_types),
("taskTypes", task_types),
("linkTypes", link_types),
("statuses", statuses),
("tags", tags),
("config", config),
("attrib", attrib),
("data", data),
("active", active),
("code", project_code),
)
if value is not None
})
response = self.patch(
"projects/{}".format(project_name),
**changes
)
response.raise_for_status()
def delete_project(self, project_name):
"""Delete project from server.

View file

@ -1,2 +1,2 @@
"""Package declaring Python API for Ayon server."""
__version__ = "0.2.0"
__version__ = "0.2.1"