Streamlining Shaman protocol further, plus rough implementation for addon
This commit is contained in:
parent
668bfbc492
commit
f9b7510c42
@ -56,7 +56,7 @@ def _default_job_name() -> str:
|
|||||||
|
|
||||||
|
|
||||||
@bpy.app.handlers.persistent
|
@bpy.app.handlers.persistent
|
||||||
def _set_flamenco_job_name(a, b) -> None:
|
def _set_flamenco_job_name(a, b):
|
||||||
scene = bpy.context.scene
|
scene = bpy.context.scene
|
||||||
if scene.flamenco_job_name:
|
if scene.flamenco_job_name:
|
||||||
return
|
return
|
||||||
@ -65,7 +65,7 @@ def _set_flamenco_job_name(a, b) -> None:
|
|||||||
|
|
||||||
|
|
||||||
@bpy.app.handlers.persistent
|
@bpy.app.handlers.persistent
|
||||||
def _unset_flamenco_job_name(a, b) -> None:
|
def _unset_flamenco_job_name(a, b):
|
||||||
scene = bpy.context.scene
|
scene = bpy.context.scene
|
||||||
if scene.flamenco_job_name != _default_job_name():
|
if scene.flamenco_job_name != _default_job_name():
|
||||||
return
|
return
|
||||||
|
0
addon/flamenco/bat/__init__.py
Normal file
0
addon/flamenco/bat/__init__.py
Normal file
205
addon/flamenco/bat/cache.py
Normal file
205
addon/flamenco/bat/cache.py
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
#
|
||||||
|
# ***** END GPL LICENCE BLOCK *****
|
||||||
|
#
|
||||||
|
# (c) 2019, Blender Foundation - Sybren A. Stüvel
|
||||||
|
|
||||||
|
import base64
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import typing
|
||||||
|
from collections import deque
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from . import time_tracker
|
||||||
|
|
||||||
|
CACHE_ROOT = Path().home() / ".cache/shaman-client/shasums"
|
||||||
|
MAX_CACHE_FILES_AGE_SECS = 3600 * 24 * 60 # 60 days
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class TimeInfo:
|
||||||
|
computing_checksums = 0.0
|
||||||
|
checksum_cache_handling = 0.0
|
||||||
|
|
||||||
|
|
||||||
|
def find_files(root: Path) -> typing.Iterable[Path]:
|
||||||
|
"""Recursively finds files in the given root path.
|
||||||
|
|
||||||
|
Directories are recursed into, and file paths are yielded.
|
||||||
|
Symlinks are yielded if they refer to a regular file.
|
||||||
|
"""
|
||||||
|
queue = deque([root])
|
||||||
|
while queue:
|
||||||
|
path = queue.popleft()
|
||||||
|
|
||||||
|
# Ignore hidden files/dirs; these can be things like '.svn' or '.git',
|
||||||
|
# which shouldn't be sent to Shaman.
|
||||||
|
if path.name.startswith("."):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if path.is_dir():
|
||||||
|
for child in path.iterdir():
|
||||||
|
queue.append(child)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Only yield symlinks if they link to (a link to) a normal file.
|
||||||
|
if path.is_symlink():
|
||||||
|
symlinked = path.resolve()
|
||||||
|
if symlinked.is_file():
|
||||||
|
yield path
|
||||||
|
continue
|
||||||
|
|
||||||
|
if path.is_file():
|
||||||
|
yield path
|
||||||
|
|
||||||
|
|
||||||
|
def compute_checksum(filepath: Path) -> str:
|
||||||
|
"""Compute the SHA256 checksum for the given file."""
|
||||||
|
blocksize = 32 * 1024
|
||||||
|
|
||||||
|
log.debug("Computing checksum of %s", filepath)
|
||||||
|
with time_tracker.track_time(TimeInfo, "computing_checksums"):
|
||||||
|
hasher = hashlib.sha256()
|
||||||
|
with filepath.open("rb") as infile:
|
||||||
|
while True:
|
||||||
|
block = infile.read(blocksize)
|
||||||
|
if not block:
|
||||||
|
break
|
||||||
|
hasher.update(block)
|
||||||
|
checksum = hasher.hexdigest()
|
||||||
|
return checksum
|
||||||
|
|
||||||
|
|
||||||
|
def _cache_path(filepath: Path) -> Path:
|
||||||
|
"""Compute the cache file for the given file path."""
|
||||||
|
|
||||||
|
fs_encoding = sys.getfilesystemencoding()
|
||||||
|
filepath = filepath.absolute()
|
||||||
|
|
||||||
|
# Reverse the directory, because most variation is in the last bytes.
|
||||||
|
rev_dir = str(filepath.parent)[::-1]
|
||||||
|
encoded_path = filepath.stem + rev_dir + filepath.suffix
|
||||||
|
cache_key = (
|
||||||
|
base64.urlsafe_b64encode(encoded_path.encode(fs_encoding)).decode().rstrip("=")
|
||||||
|
)
|
||||||
|
|
||||||
|
cache_path = CACHE_ROOT / cache_key[:10] / cache_key[10:]
|
||||||
|
return cache_path
|
||||||
|
|
||||||
|
|
||||||
|
def compute_cached_checksum(filepath: Path) -> str:
|
||||||
|
"""Computes the SHA256 checksum.
|
||||||
|
|
||||||
|
The checksum is cached to disk. If the cache is still valid, it is used to
|
||||||
|
skip the actual SHA256 computation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
with time_tracker.track_time(TimeInfo, "checksum_cache_handling"):
|
||||||
|
current_stat = filepath.stat()
|
||||||
|
cache_path = _cache_path(filepath)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with cache_path.open("r") as cache_file:
|
||||||
|
payload = json.load(cache_file)
|
||||||
|
except (OSError, ValueError):
|
||||||
|
# File may not exist, or have invalid contents.
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
checksum: str = payload.get("checksum", "")
|
||||||
|
cached_mtime = payload.get("file_mtime", 0.0)
|
||||||
|
cached_size = payload.get("file_size", -1)
|
||||||
|
|
||||||
|
if (
|
||||||
|
checksum
|
||||||
|
and current_stat.st_size == cached_size
|
||||||
|
and abs(cached_mtime - current_stat.st_mtime) < 0.01
|
||||||
|
):
|
||||||
|
cache_path.touch()
|
||||||
|
return checksum
|
||||||
|
|
||||||
|
checksum = compute_checksum(filepath)
|
||||||
|
|
||||||
|
with time_tracker.track_time(TimeInfo, "checksum_cache_handling"):
|
||||||
|
payload = {
|
||||||
|
"checksum": checksum,
|
||||||
|
"file_mtime": current_stat.st_mtime,
|
||||||
|
"file_size": current_stat.st_size,
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
cache_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
with cache_path.open("w") as cache_file:
|
||||||
|
json.dump(payload, cache_file)
|
||||||
|
except IOError as ex:
|
||||||
|
log.warning("Unable to write checksum cache file %s: %s", cache_path, ex)
|
||||||
|
|
||||||
|
return checksum
|
||||||
|
|
||||||
|
|
||||||
|
def cleanup_cache() -> None:
|
||||||
|
"""Remove all cache files that are older than MAX_CACHE_FILES_AGE_SECS."""
|
||||||
|
|
||||||
|
if not CACHE_ROOT.exists():
|
||||||
|
return
|
||||||
|
|
||||||
|
with time_tracker.track_time(TimeInfo, "checksum_cache_handling"):
|
||||||
|
queue = deque([CACHE_ROOT])
|
||||||
|
rmdir_queue = []
|
||||||
|
|
||||||
|
now = time.time()
|
||||||
|
num_removed_files = 0
|
||||||
|
num_removed_dirs = 0
|
||||||
|
while queue:
|
||||||
|
path = queue.popleft()
|
||||||
|
|
||||||
|
if path.is_dir():
|
||||||
|
queue.extend(path.iterdir())
|
||||||
|
rmdir_queue.append(path)
|
||||||
|
continue
|
||||||
|
|
||||||
|
assert path.is_file()
|
||||||
|
path.relative_to(CACHE_ROOT)
|
||||||
|
|
||||||
|
age = now - path.stat().st_mtime
|
||||||
|
# Don't trust files from the future either.
|
||||||
|
if 0 <= age <= MAX_CACHE_FILES_AGE_SECS:
|
||||||
|
continue
|
||||||
|
|
||||||
|
path.unlink()
|
||||||
|
num_removed_files += 1
|
||||||
|
|
||||||
|
for dirpath in reversed(rmdir_queue):
|
||||||
|
assert dirpath.is_dir()
|
||||||
|
dirpath.relative_to(CACHE_ROOT)
|
||||||
|
|
||||||
|
try:
|
||||||
|
dirpath.rmdir()
|
||||||
|
num_removed_dirs += 1
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if num_removed_dirs or num_removed_files:
|
||||||
|
log.info(
|
||||||
|
"Cache Cleanup: removed %d dirs and %d files",
|
||||||
|
num_removed_dirs,
|
||||||
|
num_removed_files,
|
||||||
|
)
|
@ -1,3 +1,4 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
"""BAT packing interface for Flamenco."""
|
"""BAT packing interface for Flamenco."""
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
@ -8,7 +9,7 @@ import queue
|
|||||||
import threading
|
import threading
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from . import wheels
|
from .. import wheels
|
||||||
|
|
||||||
pack = wheels.load_wheel("blender_asset_tracer.pack")
|
pack = wheels.load_wheel("blender_asset_tracer.pack")
|
||||||
progress = wheels.load_wheel("blender_asset_tracer.pack.progress")
|
progress = wheels.load_wheel("blender_asset_tracer.pack.progress")
|
||||||
@ -122,39 +123,6 @@ class BatProgress(progress.Callback): # type: ignore
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
# class ShamanPacker(shaman.ShamanPacker):
|
|
||||||
# """Packer with support for getting an auth token from Flamenco Server."""
|
|
||||||
|
|
||||||
# def __init__(
|
|
||||||
# self,
|
|
||||||
# bfile: Path,
|
|
||||||
# project: Path,
|
|
||||||
# target: str,
|
|
||||||
# endpoint: str,
|
|
||||||
# checkout_id: str,
|
|
||||||
# *,
|
|
||||||
# manager_id: str,
|
|
||||||
# **kwargs
|
|
||||||
# ) -> None:
|
|
||||||
# self.manager_id = manager_id
|
|
||||||
# super().__init__(bfile, project, target, endpoint, checkout_id, **kwargs)
|
|
||||||
|
|
||||||
# def _get_auth_token(self) -> str:
|
|
||||||
# """get a token from Flamenco Server"""
|
|
||||||
|
|
||||||
# from ..blender import PILLAR_SERVER_URL
|
|
||||||
# from ..pillar import blender_id_subclient, uncached_session, SUBCLIENT_ID
|
|
||||||
|
|
||||||
# url = urllib.parse.urljoin(
|
|
||||||
# PILLAR_SERVER_URL, "flamenco/jwt/generate-token/%s" % self.manager_id
|
|
||||||
# )
|
|
||||||
# auth_token = blender_id_subclient()["token"]
|
|
||||||
|
|
||||||
# resp = uncached_session.get(url, auth=(auth_token, SUBCLIENT_ID))
|
|
||||||
# resp.raise_for_status()
|
|
||||||
# return resp.text
|
|
||||||
|
|
||||||
|
|
||||||
class PackThread(threading.Thread):
|
class PackThread(threading.Thread):
|
||||||
queue: queue.SimpleQueue[Message]
|
queue: queue.SimpleQueue[Message]
|
||||||
|
|
||||||
@ -228,7 +196,7 @@ def copy( # type: ignore
|
|||||||
exclusion_filter: str,
|
exclusion_filter: str,
|
||||||
*,
|
*,
|
||||||
relative_only: bool,
|
relative_only: bool,
|
||||||
packer_class=pack.Packer, # type: ignore
|
packer_class=pack.Packer,
|
||||||
**packer_args: dict[Any, Any],
|
**packer_args: dict[Any, Any],
|
||||||
) -> PackThread:
|
) -> PackThread:
|
||||||
"""Use BAT to copy the given file and dependencies to the target location.
|
"""Use BAT to copy the given file and dependencies to the target location.
|
440
addon/flamenco/bat/shaman.py
Normal file
440
addon/flamenco/bat/shaman.py
Normal file
@ -0,0 +1,440 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
"""BAT interface for sending files to the Manager via the Shaman API."""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import random
|
||||||
|
from collections import deque
|
||||||
|
from pathlib import Path, PurePath, PurePosixPath
|
||||||
|
from typing import TYPE_CHECKING, Optional, Any
|
||||||
|
|
||||||
|
from .. import wheels
|
||||||
|
from . import cache
|
||||||
|
|
||||||
|
bat_pack = wheels.load_wheel("blender_asset_tracer.pack")
|
||||||
|
bat_transfer = wheels.load_wheel("blender_asset_tracer.pack.transfer")
|
||||||
|
bat_bpathlib = wheels.load_wheel("blender_asset_tracer.bpathlib")
|
||||||
|
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from ..manager import ApiClient as _ApiClient
|
||||||
|
|
||||||
|
from ..manager.models import (
|
||||||
|
ShamanRequirementsRequest as _ShamanRequirementsRequest,
|
||||||
|
ShamanRequirementsResponse as _ShamanRequirementsResponse,
|
||||||
|
ShamanFileSpec as _ShamanFileSpec,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
_ApiClient = object
|
||||||
|
_ShamanRequirementsRequest = object
|
||||||
|
_ShamanRequirementsResponse = object
|
||||||
|
_ShamanFileSpec = object
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
MAX_DEFERRED_PATHS = 8
|
||||||
|
MAX_FAILED_PATHS = 8
|
||||||
|
|
||||||
|
|
||||||
|
# Mypy doesn't understand that bat_pack.Packer exists.
|
||||||
|
class Packer(bat_pack.Packer): # type: ignore
|
||||||
|
"""Creates BAT Packs on a Shaman server."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
blendfile: Path,
|
||||||
|
project_root: Path,
|
||||||
|
target: str,
|
||||||
|
api_client: _ApiClient,
|
||||||
|
checkout_path: str,
|
||||||
|
**kwargs: dict[Any, Any],
|
||||||
|
) -> None:
|
||||||
|
"""Constructor
|
||||||
|
|
||||||
|
:param target: mock target root directory to construct project-relative paths.
|
||||||
|
"""
|
||||||
|
super().__init__(blendfile, project_root, target, **kwargs)
|
||||||
|
self.checkout_path = checkout_path
|
||||||
|
self.api_client = api_client
|
||||||
|
|
||||||
|
# Mypy doesn't understand that bat_transfer.FileTransferer exists.
|
||||||
|
def _create_file_transferer(self) -> bat_transfer.FileTransferer: # type: ignore
|
||||||
|
return Transferrer(self.api_client, self.project, self.checkout_path)
|
||||||
|
|
||||||
|
def _make_target_path(self, target: str) -> PurePath:
|
||||||
|
return PurePosixPath("/")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def output_path(self) -> PurePath:
|
||||||
|
"""The path of the packed blend file in the target directory."""
|
||||||
|
assert self._output_path is not None
|
||||||
|
|
||||||
|
checkout_location = PurePosixPath(self.checkout_path)
|
||||||
|
rel_output = self._output_path.relative_to(self._target_path)
|
||||||
|
out_path: PurePath = checkout_location / rel_output
|
||||||
|
return out_path
|
||||||
|
|
||||||
|
def execute(self):
|
||||||
|
try:
|
||||||
|
super().execute()
|
||||||
|
except Exception as ex:
|
||||||
|
log.exception("Error communicating with Shaman")
|
||||||
|
self.abort(str(ex))
|
||||||
|
self._check_aborted()
|
||||||
|
|
||||||
|
|
||||||
|
class Transferrer(bat_transfer.FileTransferer): # type: ignore
|
||||||
|
"""Sends files to a Shaman server."""
|
||||||
|
|
||||||
|
class AbortUpload(Exception):
|
||||||
|
"""Raised from the upload callback to abort an upload."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
api_client: _ApiClient,
|
||||||
|
local_project_root: Path,
|
||||||
|
checkout_path: str,
|
||||||
|
) -> None:
|
||||||
|
super().__init__()
|
||||||
|
from ..manager.apis import ShamanApi
|
||||||
|
|
||||||
|
self.shaman_api = ShamanApi(api_client)
|
||||||
|
|
||||||
|
self.project_root = local_project_root
|
||||||
|
self.checkout_path = checkout_path
|
||||||
|
self.log = log.getChild(self.__class__.__name__)
|
||||||
|
self.uploaded_files = 0
|
||||||
|
self.uploaded_bytes = 0
|
||||||
|
|
||||||
|
# Mapping from the relative path (as used in Shaman requests) to the
|
||||||
|
# absolute path where we can find the local file. This is typically just
|
||||||
|
# the same as the relative path (relative to the project root), but can
|
||||||
|
# also point to a temporary file when it had to be rewritten.
|
||||||
|
self._rel_to_local_path: dict[str, Path] = {}
|
||||||
|
|
||||||
|
# Temporary files that should be deleted before stopping.
|
||||||
|
self._delete_when_done: list[Path] = []
|
||||||
|
|
||||||
|
# noinspection PyBroadException
|
||||||
|
def run(self) -> None:
|
||||||
|
try:
|
||||||
|
self._run()
|
||||||
|
except Exception as ex:
|
||||||
|
# We have to catch exceptions in a broad way, as this is running in
|
||||||
|
# a separate thread, and exceptions won't otherwise be seen.
|
||||||
|
self.log.exception("Error transferring files to Shaman")
|
||||||
|
self.error_set("Unexpected exception transferring files to Shaman: %s" % ex)
|
||||||
|
finally:
|
||||||
|
# Delete the files that were supposed to be moved.
|
||||||
|
for src in self._delete_when_done:
|
||||||
|
self.delete_file(src)
|
||||||
|
self._delete_when_done.clear()
|
||||||
|
|
||||||
|
def _run(self) -> None:
|
||||||
|
self.uploaded_files = 0
|
||||||
|
self.uploaded_bytes = 0
|
||||||
|
|
||||||
|
# Construct the Shaman Checkout Definition file.
|
||||||
|
shaman_file_specs = self._create_checkout_definition()
|
||||||
|
if not shaman_file_specs:
|
||||||
|
# An error has already been logged.
|
||||||
|
return
|
||||||
|
|
||||||
|
failed_files = self._upload_missing_files(shaman_file_specs)
|
||||||
|
if failed_files:
|
||||||
|
self.log.error("Aborting upload due to too many failures")
|
||||||
|
self.error_set("Giving up after multiple attempts to upload the files")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.log.info("All files uploaded succesfully")
|
||||||
|
self._request_checkout(shaman_file_specs)
|
||||||
|
|
||||||
|
def _upload_missing_files(
|
||||||
|
self, shaman_file_specs: _ShamanRequirementsRequest
|
||||||
|
) -> set[_ShamanFileSpec]:
|
||||||
|
self.log.info("Feeding %d files to the Shaman", len(shaman_file_specs.files))
|
||||||
|
if self.log.isEnabledFor(logging.INFO):
|
||||||
|
for spec in shaman_file_specs.files:
|
||||||
|
self.log.info(" - %s", spec.path)
|
||||||
|
|
||||||
|
# Try to upload all the files.
|
||||||
|
failed_files: set[_ShamanFileSpec] = set()
|
||||||
|
max_tries = 50
|
||||||
|
for try_index in range(max_tries):
|
||||||
|
# Send the file to the Shaman and see what we still need to send there.
|
||||||
|
to_upload = self._send_checkout_def_to_shaman(shaman_file_specs)
|
||||||
|
if to_upload is None:
|
||||||
|
# An error has already been logged.
|
||||||
|
return failed_files
|
||||||
|
|
||||||
|
if not to_upload:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Send the files that still need to be sent.
|
||||||
|
self.log.info("Upload attempt %d", try_index + 1)
|
||||||
|
failed_files = self._upload_files(to_upload)
|
||||||
|
if not failed_files:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Having failed paths at this point is expected when multiple
|
||||||
|
# clients are sending the same files. Instead of retrying on a
|
||||||
|
# file-by-file basis, we just re-send the checkout definition
|
||||||
|
# file to the Shaman and obtain a new list of files to upload.
|
||||||
|
return failed_files
|
||||||
|
|
||||||
|
def _create_checkout_definition(self) -> Optional[_ShamanRequirementsRequest]:
|
||||||
|
"""Create the checkout definition file for this BAT pack.
|
||||||
|
|
||||||
|
:returns: the checkout definition.
|
||||||
|
|
||||||
|
If there was an error and file transfer was aborted, the checkout
|
||||||
|
definition will be empty.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from ..manager.models import (
|
||||||
|
ShamanRequirementsRequest,
|
||||||
|
ShamanFileSpec,
|
||||||
|
)
|
||||||
|
|
||||||
|
filespecs: list[ShamanFileSpec] = []
|
||||||
|
|
||||||
|
for src, dst, act in self.iter_queue():
|
||||||
|
try:
|
||||||
|
checksum = cache.compute_cached_checksum(src)
|
||||||
|
filesize = src.stat().st_size
|
||||||
|
relpath: str = bat_bpathlib.strip_root(dst)
|
||||||
|
|
||||||
|
filespec = ShamanFileSpec(
|
||||||
|
sha=checksum,
|
||||||
|
size=filesize,
|
||||||
|
path=relpath,
|
||||||
|
)
|
||||||
|
filespecs.append(filespec)
|
||||||
|
self._rel_to_local_path[relpath] = src
|
||||||
|
|
||||||
|
if act == bat_transfer.Action.MOVE:
|
||||||
|
self._delete_when_done.append(src)
|
||||||
|
except Exception:
|
||||||
|
# We have to catch exceptions in a broad way, as this is running in
|
||||||
|
# a separate thread, and exceptions won't otherwise be seen.
|
||||||
|
msg = "Error transferring %s to %s" % (src, dst)
|
||||||
|
self.log.exception(msg)
|
||||||
|
# Put the files to copy back into the queue, and abort. This allows
|
||||||
|
# the main thread to inspect the queue and see which files were not
|
||||||
|
# copied. The one we just failed (due to this exception) should also
|
||||||
|
# be reported there.
|
||||||
|
self.queue.put((src, dst, act))
|
||||||
|
self.error_set(msg)
|
||||||
|
return None
|
||||||
|
|
||||||
|
cache.cleanup_cache()
|
||||||
|
specs: ShamanRequirementsRequest = ShamanRequirementsRequest(files=filespecs)
|
||||||
|
return specs
|
||||||
|
|
||||||
|
def _send_checkout_def_to_shaman(
|
||||||
|
self,
|
||||||
|
requirements: _ShamanRequirementsRequest,
|
||||||
|
) -> Optional[deque[_ShamanFileSpec]]:
|
||||||
|
"""Send the checkout definition file to the Shaman.
|
||||||
|
|
||||||
|
:return: An iterable of file specs that still need to be uploaded, or
|
||||||
|
None if there was an error.
|
||||||
|
"""
|
||||||
|
from ..manager.exceptions import ApiException
|
||||||
|
|
||||||
|
try:
|
||||||
|
resp = self.shaman_api.shaman_checkout_requirements(requirements)
|
||||||
|
except ApiException as ex:
|
||||||
|
# TODO: the body should be JSON of a predefined type, parse it to get the actual message.
|
||||||
|
msg = "Error from Shaman, code %d: %s" % (ex.status, ex.body)
|
||||||
|
self.log.error(msg)
|
||||||
|
self.error_set(msg)
|
||||||
|
return None
|
||||||
|
assert isinstance(resp, _ShamanRequirementsResponse)
|
||||||
|
|
||||||
|
to_upload: deque[_ShamanFileSpec] = deque()
|
||||||
|
for file_spec in resp.files:
|
||||||
|
if file_spec.path not in self._rel_to_local_path:
|
||||||
|
msg = (
|
||||||
|
"Shaman requested path we did not intend to upload: %r" % file_spec
|
||||||
|
)
|
||||||
|
self.log.error(msg)
|
||||||
|
self.error_set(msg)
|
||||||
|
return None
|
||||||
|
|
||||||
|
self.log.debug(" %s: %s", file_spec.status, file_spec.path)
|
||||||
|
match file_spec.status.value:
|
||||||
|
case "unknown":
|
||||||
|
to_upload.appendleft(file_spec)
|
||||||
|
case "uploading":
|
||||||
|
to_upload.append(file_spec)
|
||||||
|
case _:
|
||||||
|
msg = "Unknown status in response from Shaman: %r" % file_spec
|
||||||
|
self.log.error(msg)
|
||||||
|
self.error_set(msg)
|
||||||
|
return None
|
||||||
|
return to_upload
|
||||||
|
|
||||||
|
def _upload_files(self, to_upload: deque[_ShamanFileSpec]) -> set[_ShamanFileSpec]:
|
||||||
|
"""Actually upload the files to Shaman.
|
||||||
|
|
||||||
|
Returns the set of files that we did not upload.
|
||||||
|
"""
|
||||||
|
if not to_upload:
|
||||||
|
self.log.info("All files are at the Shaman already")
|
||||||
|
self.report_transferred(0)
|
||||||
|
return set()
|
||||||
|
|
||||||
|
from ..manager.exceptions import ApiException
|
||||||
|
|
||||||
|
failed_specs: set[_ShamanFileSpec] = set()
|
||||||
|
deferred_specs: set[_ShamanFileSpec] = set()
|
||||||
|
|
||||||
|
def defer(filespec: _ShamanFileSpec) -> None:
|
||||||
|
nonlocal to_upload
|
||||||
|
|
||||||
|
self.log.info(
|
||||||
|
" %s deferred (already being uploaded by someone else)", filespec.path
|
||||||
|
)
|
||||||
|
deferred_specs.add(filespec)
|
||||||
|
|
||||||
|
# Instead of deferring this one file, randomize the files to upload.
|
||||||
|
# This prevents multiple deferrals when someone else is uploading
|
||||||
|
# files from the same project (because it probably happens alphabetically).
|
||||||
|
all_files = list(to_upload)
|
||||||
|
random.shuffle(all_files)
|
||||||
|
to_upload = deque(all_files)
|
||||||
|
|
||||||
|
self.log.info(
|
||||||
|
"Going to upload %d of %d files", len(to_upload), len(self._spec_to_paths)
|
||||||
|
)
|
||||||
|
while to_upload:
|
||||||
|
# After too many failures, just retry to get a fresh set of files to upload.
|
||||||
|
if len(failed_specs) > MAX_FAILED_PATHS:
|
||||||
|
self.log.info("Too many failures, going to abort this iteration")
|
||||||
|
failed_specs.update(to_upload)
|
||||||
|
return failed_specs
|
||||||
|
|
||||||
|
file_spec = to_upload.popleft()
|
||||||
|
self.log.info(" %s", file_spec.path)
|
||||||
|
|
||||||
|
# Pre-flight check. The generated API code will load the entire file into
|
||||||
|
# memory before sending it to the Shaman. It's faster to do a check at
|
||||||
|
# Shaman first, to see if we need uploading at all.
|
||||||
|
check_resp = self.shaman_api.shaman_file_store_check(
|
||||||
|
checksum=file_spec.sha,
|
||||||
|
filesize=file_spec.size,
|
||||||
|
)
|
||||||
|
if check_resp.status.value == "stored":
|
||||||
|
self.log.info(" %s: skipping, already on server", file_spec.path)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Let the Shaman know whether we can defer uploading this file or not.
|
||||||
|
can_defer = (
|
||||||
|
len(deferred_specs) < MAX_DEFERRED_PATHS
|
||||||
|
and file_spec not in deferred_specs
|
||||||
|
and len(to_upload)
|
||||||
|
)
|
||||||
|
|
||||||
|
local_filepath = self._rel_to_local_path[file_spec.path]
|
||||||
|
try:
|
||||||
|
with local_filepath.open("rb") as file_reader:
|
||||||
|
self.shaman_api.shaman_file_store(
|
||||||
|
checksum=file_spec.sha,
|
||||||
|
filesize=file_spec.size,
|
||||||
|
body=file_reader,
|
||||||
|
x_shaman_can_defer_upload=can_defer,
|
||||||
|
x_shaman_original_filename=file_spec.path,
|
||||||
|
)
|
||||||
|
except ApiException as ex:
|
||||||
|
match ex.status:
|
||||||
|
case 425: # Too Early, i.e. defer uploading this file.
|
||||||
|
self.log.info(
|
||||||
|
" %s: someone else is uploading this file, deferring",
|
||||||
|
file_spec.path,
|
||||||
|
)
|
||||||
|
defer(file_spec)
|
||||||
|
continue
|
||||||
|
case 417: # Expectation Failed; mismatch of checksum or file size.
|
||||||
|
msg = "Error from Shaman uploading %s, code %d: %s" % (
|
||||||
|
file_spec.path,
|
||||||
|
ex.status,
|
||||||
|
ex.body,
|
||||||
|
)
|
||||||
|
case _: # Unknown error
|
||||||
|
msg = "API exception\nHeaders: %s\nBody: %s\n" % (
|
||||||
|
ex.headers,
|
||||||
|
ex.body,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.log.error(msg)
|
||||||
|
self.error_set(msg)
|
||||||
|
failed_specs.add(file_spec)
|
||||||
|
return failed_specs
|
||||||
|
|
||||||
|
failed_specs.discard(file_spec)
|
||||||
|
self.uploaded_files += 1
|
||||||
|
file_size = local_filepath.stat().st_size
|
||||||
|
self.uploaded_bytes += file_size
|
||||||
|
self.report_transferred(file_size)
|
||||||
|
|
||||||
|
if failed_specs:
|
||||||
|
self.log.info(
|
||||||
|
"Uploaded %d bytes in %d files so far",
|
||||||
|
self.uploaded_bytes,
|
||||||
|
self.uploaded_files,
|
||||||
|
)
|
||||||
|
return failed_specs
|
||||||
|
|
||||||
|
self.log.info(
|
||||||
|
"Done uploading %d bytes in %d files",
|
||||||
|
self.uploaded_bytes,
|
||||||
|
self.uploaded_files,
|
||||||
|
)
|
||||||
|
return set()
|
||||||
|
|
||||||
|
def report_transferred(self, bytes_transferred: int) -> None:
|
||||||
|
if self._abort.is_set():
|
||||||
|
self.log.warning("Interrupting ongoing upload")
|
||||||
|
raise self.AbortUpload("interrupting ongoing upload")
|
||||||
|
super().report_transferred(bytes_transferred)
|
||||||
|
|
||||||
|
def _request_checkout(self, shaman_file_specs: _ShamanRequirementsRequest) -> None:
|
||||||
|
"""Ask the Shaman to create a checkout of this BAT pack."""
|
||||||
|
|
||||||
|
if not self.checkout_path:
|
||||||
|
self.log.warning("NOT requesting checkout at Shaman")
|
||||||
|
return
|
||||||
|
|
||||||
|
from ..manager.models import ShamanCheckout
|
||||||
|
from ..manager.exceptions import ApiException
|
||||||
|
|
||||||
|
self.log.info(
|
||||||
|
"Requesting checkout at Shaman for checkout_path=%r", self.checkout_path
|
||||||
|
)
|
||||||
|
|
||||||
|
checkoutRequest = ShamanCheckout(
|
||||||
|
files=shaman_file_specs.files,
|
||||||
|
checkout_path=self.checkout_path,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.shaman_api.shaman_checkout(checkoutRequest)
|
||||||
|
except ApiException as ex:
|
||||||
|
match ex.status:
|
||||||
|
case 424: # Files were missing
|
||||||
|
msg = "We did not upload some files, checkout aborted"
|
||||||
|
case 409: # Checkout already exists
|
||||||
|
msg = (
|
||||||
|
"There is already an existing checkout at %s"
|
||||||
|
% self.checkout_path
|
||||||
|
)
|
||||||
|
case _: # Unknown error
|
||||||
|
msg = "API exception\nHeaders: %s\nBody: %s\n" % (
|
||||||
|
ex.headers,
|
||||||
|
ex.body,
|
||||||
|
)
|
||||||
|
self.log.error(msg)
|
||||||
|
self.error_set(msg)
|
||||||
|
return
|
||||||
|
|
||||||
|
self.log.info("Shaman created checkout at %s", self.checkout_path)
|
32
addon/flamenco/bat/time_tracker.py
Normal file
32
addon/flamenco/bat/time_tracker.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
#
|
||||||
|
# ***** END GPL LICENCE BLOCK *****
|
||||||
|
#
|
||||||
|
# (c) 2019, Blender Foundation - Sybren A. Stüvel
|
||||||
|
import contextlib
|
||||||
|
import time
|
||||||
|
from typing import Any, Iterator
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def track_time(tracker_object: Any, attribute: str) -> Iterator[None]:
|
||||||
|
"""Context manager, tracks how long the context took to run."""
|
||||||
|
start_time = time.monotonic()
|
||||||
|
yield
|
||||||
|
duration = time.monotonic() - start_time
|
||||||
|
tracked_so_far = getattr(tracker_object, attribute, 0.0)
|
||||||
|
setattr(tracker_object, attribute, tracked_so_far + duration)
|
@ -10,7 +10,7 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
__version__ = "7bfde1df-dirty"
|
__version__ = "63793f42-dirty"
|
||||||
|
|
||||||
# import ApiClient
|
# import ApiClient
|
||||||
from flamenco.manager.api_client import ApiClient
|
from flamenco.manager.api_client import ApiClient
|
||||||
|
591
addon/flamenco/manager/api/shaman_api.py
Normal file
591
addon/flamenco/manager/api/shaman_api.py
Normal file
@ -0,0 +1,591 @@
|
|||||||
|
"""
|
||||||
|
Flamenco manager
|
||||||
|
|
||||||
|
Render Farm manager API # noqa: E501
|
||||||
|
|
||||||
|
The version of the OpenAPI document: 1.0.0
|
||||||
|
Generated by: https://openapi-generator.tech
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import re # noqa: F401
|
||||||
|
import sys # noqa: F401
|
||||||
|
|
||||||
|
from flamenco.manager.api_client import ApiClient, Endpoint as _Endpoint
|
||||||
|
from flamenco.manager.model_utils import ( # noqa: F401
|
||||||
|
check_allowed_values,
|
||||||
|
check_validations,
|
||||||
|
date,
|
||||||
|
datetime,
|
||||||
|
file_type,
|
||||||
|
none_type,
|
||||||
|
validate_and_convert_types
|
||||||
|
)
|
||||||
|
from flamenco.manager.model.error import Error
|
||||||
|
from flamenco.manager.model.shaman_checkout import ShamanCheckout
|
||||||
|
from flamenco.manager.model.shaman_requirements_request import ShamanRequirementsRequest
|
||||||
|
from flamenco.manager.model.shaman_requirements_response import ShamanRequirementsResponse
|
||||||
|
from flamenco.manager.model.shaman_single_file_status import ShamanSingleFileStatus
|
||||||
|
|
||||||
|
|
||||||
|
class ShamanApi(object):
|
||||||
|
"""NOTE: This class is auto generated by OpenAPI Generator
|
||||||
|
Ref: https://openapi-generator.tech
|
||||||
|
|
||||||
|
Do not edit the class manually.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, api_client=None):
|
||||||
|
if api_client is None:
|
||||||
|
api_client = ApiClient()
|
||||||
|
self.api_client = api_client
|
||||||
|
self.shaman_checkout_endpoint = _Endpoint(
|
||||||
|
settings={
|
||||||
|
'response_type': None,
|
||||||
|
'auth': [],
|
||||||
|
'endpoint_path': '/shaman/checkout/create',
|
||||||
|
'operation_id': 'shaman_checkout',
|
||||||
|
'http_method': 'POST',
|
||||||
|
'servers': None,
|
||||||
|
},
|
||||||
|
params_map={
|
||||||
|
'all': [
|
||||||
|
'shaman_checkout',
|
||||||
|
],
|
||||||
|
'required': [
|
||||||
|
'shaman_checkout',
|
||||||
|
],
|
||||||
|
'nullable': [
|
||||||
|
],
|
||||||
|
'enum': [
|
||||||
|
],
|
||||||
|
'validation': [
|
||||||
|
]
|
||||||
|
},
|
||||||
|
root_map={
|
||||||
|
'validations': {
|
||||||
|
},
|
||||||
|
'allowed_values': {
|
||||||
|
},
|
||||||
|
'openapi_types': {
|
||||||
|
'shaman_checkout':
|
||||||
|
(ShamanCheckout,),
|
||||||
|
},
|
||||||
|
'attribute_map': {
|
||||||
|
},
|
||||||
|
'location_map': {
|
||||||
|
'shaman_checkout': 'body',
|
||||||
|
},
|
||||||
|
'collection_format_map': {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
headers_map={
|
||||||
|
'accept': [
|
||||||
|
'application/json'
|
||||||
|
],
|
||||||
|
'content_type': [
|
||||||
|
'application/json'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
api_client=api_client
|
||||||
|
)
|
||||||
|
self.shaman_checkout_requirements_endpoint = _Endpoint(
|
||||||
|
settings={
|
||||||
|
'response_type': (ShamanRequirementsResponse,),
|
||||||
|
'auth': [],
|
||||||
|
'endpoint_path': '/shaman/checkout/requirements',
|
||||||
|
'operation_id': 'shaman_checkout_requirements',
|
||||||
|
'http_method': 'POST',
|
||||||
|
'servers': None,
|
||||||
|
},
|
||||||
|
params_map={
|
||||||
|
'all': [
|
||||||
|
'shaman_requirements_request',
|
||||||
|
],
|
||||||
|
'required': [
|
||||||
|
'shaman_requirements_request',
|
||||||
|
],
|
||||||
|
'nullable': [
|
||||||
|
],
|
||||||
|
'enum': [
|
||||||
|
],
|
||||||
|
'validation': [
|
||||||
|
]
|
||||||
|
},
|
||||||
|
root_map={
|
||||||
|
'validations': {
|
||||||
|
},
|
||||||
|
'allowed_values': {
|
||||||
|
},
|
||||||
|
'openapi_types': {
|
||||||
|
'shaman_requirements_request':
|
||||||
|
(ShamanRequirementsRequest,),
|
||||||
|
},
|
||||||
|
'attribute_map': {
|
||||||
|
},
|
||||||
|
'location_map': {
|
||||||
|
'shaman_requirements_request': 'body',
|
||||||
|
},
|
||||||
|
'collection_format_map': {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
headers_map={
|
||||||
|
'accept': [
|
||||||
|
'application/json'
|
||||||
|
],
|
||||||
|
'content_type': [
|
||||||
|
'application/json'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
api_client=api_client
|
||||||
|
)
|
||||||
|
self.shaman_file_store_endpoint = _Endpoint(
|
||||||
|
settings={
|
||||||
|
'response_type': None,
|
||||||
|
'auth': [],
|
||||||
|
'endpoint_path': '/shaman/files/{checksum}/{filesize}',
|
||||||
|
'operation_id': 'shaman_file_store',
|
||||||
|
'http_method': 'POST',
|
||||||
|
'servers': None,
|
||||||
|
},
|
||||||
|
params_map={
|
||||||
|
'all': [
|
||||||
|
'checksum',
|
||||||
|
'filesize',
|
||||||
|
'body',
|
||||||
|
'x_shaman_can_defer_upload',
|
||||||
|
'x_shaman_original_filename',
|
||||||
|
],
|
||||||
|
'required': [
|
||||||
|
'checksum',
|
||||||
|
'filesize',
|
||||||
|
'body',
|
||||||
|
],
|
||||||
|
'nullable': [
|
||||||
|
],
|
||||||
|
'enum': [
|
||||||
|
],
|
||||||
|
'validation': [
|
||||||
|
]
|
||||||
|
},
|
||||||
|
root_map={
|
||||||
|
'validations': {
|
||||||
|
},
|
||||||
|
'allowed_values': {
|
||||||
|
},
|
||||||
|
'openapi_types': {
|
||||||
|
'checksum':
|
||||||
|
(str,),
|
||||||
|
'filesize':
|
||||||
|
(int,),
|
||||||
|
'body':
|
||||||
|
(file_type,),
|
||||||
|
'x_shaman_can_defer_upload':
|
||||||
|
(bool,),
|
||||||
|
'x_shaman_original_filename':
|
||||||
|
(str,),
|
||||||
|
},
|
||||||
|
'attribute_map': {
|
||||||
|
'checksum': 'checksum',
|
||||||
|
'filesize': 'filesize',
|
||||||
|
'x_shaman_can_defer_upload': 'X-Shaman-Can-Defer-Upload',
|
||||||
|
'x_shaman_original_filename': 'X-Shaman-Original-Filename',
|
||||||
|
},
|
||||||
|
'location_map': {
|
||||||
|
'checksum': 'path',
|
||||||
|
'filesize': 'path',
|
||||||
|
'body': 'body',
|
||||||
|
'x_shaman_can_defer_upload': 'header',
|
||||||
|
'x_shaman_original_filename': 'header',
|
||||||
|
},
|
||||||
|
'collection_format_map': {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
headers_map={
|
||||||
|
'accept': [
|
||||||
|
'application/json'
|
||||||
|
],
|
||||||
|
'content_type': [
|
||||||
|
'application/octet-stream'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
api_client=api_client
|
||||||
|
)
|
||||||
|
self.shaman_file_store_check_endpoint = _Endpoint(
|
||||||
|
settings={
|
||||||
|
'response_type': (ShamanSingleFileStatus,),
|
||||||
|
'auth': [],
|
||||||
|
'endpoint_path': '/shaman/files/{checksum}/{filesize}',
|
||||||
|
'operation_id': 'shaman_file_store_check',
|
||||||
|
'http_method': 'OPTIONS',
|
||||||
|
'servers': None,
|
||||||
|
},
|
||||||
|
params_map={
|
||||||
|
'all': [
|
||||||
|
'checksum',
|
||||||
|
'filesize',
|
||||||
|
],
|
||||||
|
'required': [
|
||||||
|
'checksum',
|
||||||
|
'filesize',
|
||||||
|
],
|
||||||
|
'nullable': [
|
||||||
|
],
|
||||||
|
'enum': [
|
||||||
|
],
|
||||||
|
'validation': [
|
||||||
|
]
|
||||||
|
},
|
||||||
|
root_map={
|
||||||
|
'validations': {
|
||||||
|
},
|
||||||
|
'allowed_values': {
|
||||||
|
},
|
||||||
|
'openapi_types': {
|
||||||
|
'checksum':
|
||||||
|
(str,),
|
||||||
|
'filesize':
|
||||||
|
(int,),
|
||||||
|
},
|
||||||
|
'attribute_map': {
|
||||||
|
'checksum': 'checksum',
|
||||||
|
'filesize': 'filesize',
|
||||||
|
},
|
||||||
|
'location_map': {
|
||||||
|
'checksum': 'path',
|
||||||
|
'filesize': 'path',
|
||||||
|
},
|
||||||
|
'collection_format_map': {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
headers_map={
|
||||||
|
'accept': [
|
||||||
|
'application/json'
|
||||||
|
],
|
||||||
|
'content_type': [],
|
||||||
|
},
|
||||||
|
api_client=api_client
|
||||||
|
)
|
||||||
|
|
||||||
|
def shaman_checkout(
|
||||||
|
self,
|
||||||
|
shaman_checkout,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
|
"""Create a directory, and symlink the required files into it. The files must all have been uploaded to Shaman before calling this endpoint. # noqa: E501
|
||||||
|
|
||||||
|
This method makes a synchronous HTTP request by default. To make an
|
||||||
|
asynchronous HTTP request, please pass async_req=True
|
||||||
|
|
||||||
|
>>> thread = api.shaman_checkout(shaman_checkout, async_req=True)
|
||||||
|
>>> result = thread.get()
|
||||||
|
|
||||||
|
Args:
|
||||||
|
shaman_checkout (ShamanCheckout): Set of files to check out.
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
_return_http_data_only (bool): response data without head status
|
||||||
|
code and headers. Default is True.
|
||||||
|
_preload_content (bool): if False, the urllib3.HTTPResponse object
|
||||||
|
will be returned without reading/decoding response data.
|
||||||
|
Default is True.
|
||||||
|
_request_timeout (int/float/tuple): timeout setting for this request. If
|
||||||
|
one number provided, it will be total request timeout. It can also
|
||||||
|
be a pair (tuple) of (connection, read) timeouts.
|
||||||
|
Default is None.
|
||||||
|
_check_input_type (bool): specifies if type checking
|
||||||
|
should be done one the data sent to the server.
|
||||||
|
Default is True.
|
||||||
|
_check_return_type (bool): specifies if type checking
|
||||||
|
should be done one the data received from the server.
|
||||||
|
Default is True.
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_content_type (str/None): force body content-type.
|
||||||
|
Default is None and content-type will be predicted by allowed
|
||||||
|
content-types and body.
|
||||||
|
_host_index (int/None): specifies the index of the server
|
||||||
|
that we want to use.
|
||||||
|
Default is read from the configuration.
|
||||||
|
async_req (bool): execute request asynchronously
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None
|
||||||
|
If the method is called asynchronously, returns the request
|
||||||
|
thread.
|
||||||
|
"""
|
||||||
|
kwargs['async_req'] = kwargs.get(
|
||||||
|
'async_req', False
|
||||||
|
)
|
||||||
|
kwargs['_return_http_data_only'] = kwargs.get(
|
||||||
|
'_return_http_data_only', True
|
||||||
|
)
|
||||||
|
kwargs['_preload_content'] = kwargs.get(
|
||||||
|
'_preload_content', True
|
||||||
|
)
|
||||||
|
kwargs['_request_timeout'] = kwargs.get(
|
||||||
|
'_request_timeout', None
|
||||||
|
)
|
||||||
|
kwargs['_check_input_type'] = kwargs.get(
|
||||||
|
'_check_input_type', True
|
||||||
|
)
|
||||||
|
kwargs['_check_return_type'] = kwargs.get(
|
||||||
|
'_check_return_type', True
|
||||||
|
)
|
||||||
|
kwargs['_spec_property_naming'] = kwargs.get(
|
||||||
|
'_spec_property_naming', False
|
||||||
|
)
|
||||||
|
kwargs['_content_type'] = kwargs.get(
|
||||||
|
'_content_type')
|
||||||
|
kwargs['_host_index'] = kwargs.get('_host_index')
|
||||||
|
kwargs['shaman_checkout'] = \
|
||||||
|
shaman_checkout
|
||||||
|
return self.shaman_checkout_endpoint.call_with_http_info(**kwargs)
|
||||||
|
|
||||||
|
def shaman_checkout_requirements(
|
||||||
|
self,
|
||||||
|
shaman_requirements_request,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
|
"""Checks a Shaman Requirements file, and reports which files are unknown. # noqa: E501
|
||||||
|
|
||||||
|
This method makes a synchronous HTTP request by default. To make an
|
||||||
|
asynchronous HTTP request, please pass async_req=True
|
||||||
|
|
||||||
|
>>> thread = api.shaman_checkout_requirements(shaman_requirements_request, async_req=True)
|
||||||
|
>>> result = thread.get()
|
||||||
|
|
||||||
|
Args:
|
||||||
|
shaman_requirements_request (ShamanRequirementsRequest): Set of files to check
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
_return_http_data_only (bool): response data without head status
|
||||||
|
code and headers. Default is True.
|
||||||
|
_preload_content (bool): if False, the urllib3.HTTPResponse object
|
||||||
|
will be returned without reading/decoding response data.
|
||||||
|
Default is True.
|
||||||
|
_request_timeout (int/float/tuple): timeout setting for this request. If
|
||||||
|
one number provided, it will be total request timeout. It can also
|
||||||
|
be a pair (tuple) of (connection, read) timeouts.
|
||||||
|
Default is None.
|
||||||
|
_check_input_type (bool): specifies if type checking
|
||||||
|
should be done one the data sent to the server.
|
||||||
|
Default is True.
|
||||||
|
_check_return_type (bool): specifies if type checking
|
||||||
|
should be done one the data received from the server.
|
||||||
|
Default is True.
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_content_type (str/None): force body content-type.
|
||||||
|
Default is None and content-type will be predicted by allowed
|
||||||
|
content-types and body.
|
||||||
|
_host_index (int/None): specifies the index of the server
|
||||||
|
that we want to use.
|
||||||
|
Default is read from the configuration.
|
||||||
|
async_req (bool): execute request asynchronously
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
ShamanRequirementsResponse
|
||||||
|
If the method is called asynchronously, returns the request
|
||||||
|
thread.
|
||||||
|
"""
|
||||||
|
kwargs['async_req'] = kwargs.get(
|
||||||
|
'async_req', False
|
||||||
|
)
|
||||||
|
kwargs['_return_http_data_only'] = kwargs.get(
|
||||||
|
'_return_http_data_only', True
|
||||||
|
)
|
||||||
|
kwargs['_preload_content'] = kwargs.get(
|
||||||
|
'_preload_content', True
|
||||||
|
)
|
||||||
|
kwargs['_request_timeout'] = kwargs.get(
|
||||||
|
'_request_timeout', None
|
||||||
|
)
|
||||||
|
kwargs['_check_input_type'] = kwargs.get(
|
||||||
|
'_check_input_type', True
|
||||||
|
)
|
||||||
|
kwargs['_check_return_type'] = kwargs.get(
|
||||||
|
'_check_return_type', True
|
||||||
|
)
|
||||||
|
kwargs['_spec_property_naming'] = kwargs.get(
|
||||||
|
'_spec_property_naming', False
|
||||||
|
)
|
||||||
|
kwargs['_content_type'] = kwargs.get(
|
||||||
|
'_content_type')
|
||||||
|
kwargs['_host_index'] = kwargs.get('_host_index')
|
||||||
|
kwargs['shaman_requirements_request'] = \
|
||||||
|
shaman_requirements_request
|
||||||
|
return self.shaman_checkout_requirements_endpoint.call_with_http_info(**kwargs)
|
||||||
|
|
||||||
|
def shaman_file_store(
|
||||||
|
self,
|
||||||
|
checksum,
|
||||||
|
filesize,
|
||||||
|
body,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
|
"""Store a new file on the Shaman server. Note that the Shaman server can forcibly close the HTTP connection when another client finishes uploading the exact same file, to prevent double uploads. The file's contents should be sent in the request body. # noqa: E501
|
||||||
|
|
||||||
|
This method makes a synchronous HTTP request by default. To make an
|
||||||
|
asynchronous HTTP request, please pass async_req=True
|
||||||
|
|
||||||
|
>>> thread = api.shaman_file_store(checksum, filesize, body, async_req=True)
|
||||||
|
>>> result = thread.get()
|
||||||
|
|
||||||
|
Args:
|
||||||
|
checksum (str): SHA256 checksum of the file.
|
||||||
|
filesize (int): Size of the file in bytes.
|
||||||
|
body (file_type): Contents of the file
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
x_shaman_can_defer_upload (bool): The client indicates that it can defer uploading this file. The \"208\" response will not only be returned when the file is already fully known to the Shaman server, but also when someone else is currently uploading this file. . [optional]
|
||||||
|
x_shaman_original_filename (str): The original filename. If sent along with the request, it will be included in the server logs, which can aid in debugging. . [optional]
|
||||||
|
_return_http_data_only (bool): response data without head status
|
||||||
|
code and headers. Default is True.
|
||||||
|
_preload_content (bool): if False, the urllib3.HTTPResponse object
|
||||||
|
will be returned without reading/decoding response data.
|
||||||
|
Default is True.
|
||||||
|
_request_timeout (int/float/tuple): timeout setting for this request. If
|
||||||
|
one number provided, it will be total request timeout. It can also
|
||||||
|
be a pair (tuple) of (connection, read) timeouts.
|
||||||
|
Default is None.
|
||||||
|
_check_input_type (bool): specifies if type checking
|
||||||
|
should be done one the data sent to the server.
|
||||||
|
Default is True.
|
||||||
|
_check_return_type (bool): specifies if type checking
|
||||||
|
should be done one the data received from the server.
|
||||||
|
Default is True.
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_content_type (str/None): force body content-type.
|
||||||
|
Default is None and content-type will be predicted by allowed
|
||||||
|
content-types and body.
|
||||||
|
_host_index (int/None): specifies the index of the server
|
||||||
|
that we want to use.
|
||||||
|
Default is read from the configuration.
|
||||||
|
async_req (bool): execute request asynchronously
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None
|
||||||
|
If the method is called asynchronously, returns the request
|
||||||
|
thread.
|
||||||
|
"""
|
||||||
|
kwargs['async_req'] = kwargs.get(
|
||||||
|
'async_req', False
|
||||||
|
)
|
||||||
|
kwargs['_return_http_data_only'] = kwargs.get(
|
||||||
|
'_return_http_data_only', True
|
||||||
|
)
|
||||||
|
kwargs['_preload_content'] = kwargs.get(
|
||||||
|
'_preload_content', True
|
||||||
|
)
|
||||||
|
kwargs['_request_timeout'] = kwargs.get(
|
||||||
|
'_request_timeout', None
|
||||||
|
)
|
||||||
|
kwargs['_check_input_type'] = kwargs.get(
|
||||||
|
'_check_input_type', True
|
||||||
|
)
|
||||||
|
kwargs['_check_return_type'] = kwargs.get(
|
||||||
|
'_check_return_type', True
|
||||||
|
)
|
||||||
|
kwargs['_spec_property_naming'] = kwargs.get(
|
||||||
|
'_spec_property_naming', False
|
||||||
|
)
|
||||||
|
kwargs['_content_type'] = kwargs.get(
|
||||||
|
'_content_type')
|
||||||
|
kwargs['_host_index'] = kwargs.get('_host_index')
|
||||||
|
kwargs['checksum'] = \
|
||||||
|
checksum
|
||||||
|
kwargs['filesize'] = \
|
||||||
|
filesize
|
||||||
|
kwargs['body'] = \
|
||||||
|
body
|
||||||
|
return self.shaman_file_store_endpoint.call_with_http_info(**kwargs)
|
||||||
|
|
||||||
|
def shaman_file_store_check(
|
||||||
|
self,
|
||||||
|
checksum,
|
||||||
|
filesize,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
|
"""Check the status of a file on the Shaman server. # noqa: E501
|
||||||
|
|
||||||
|
This method makes a synchronous HTTP request by default. To make an
|
||||||
|
asynchronous HTTP request, please pass async_req=True
|
||||||
|
|
||||||
|
>>> thread = api.shaman_file_store_check(checksum, filesize, async_req=True)
|
||||||
|
>>> result = thread.get()
|
||||||
|
|
||||||
|
Args:
|
||||||
|
checksum (str): SHA256 checksum of the file.
|
||||||
|
filesize (int): Size of the file in bytes.
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
_return_http_data_only (bool): response data without head status
|
||||||
|
code and headers. Default is True.
|
||||||
|
_preload_content (bool): if False, the urllib3.HTTPResponse object
|
||||||
|
will be returned without reading/decoding response data.
|
||||||
|
Default is True.
|
||||||
|
_request_timeout (int/float/tuple): timeout setting for this request. If
|
||||||
|
one number provided, it will be total request timeout. It can also
|
||||||
|
be a pair (tuple) of (connection, read) timeouts.
|
||||||
|
Default is None.
|
||||||
|
_check_input_type (bool): specifies if type checking
|
||||||
|
should be done one the data sent to the server.
|
||||||
|
Default is True.
|
||||||
|
_check_return_type (bool): specifies if type checking
|
||||||
|
should be done one the data received from the server.
|
||||||
|
Default is True.
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_content_type (str/None): force body content-type.
|
||||||
|
Default is None and content-type will be predicted by allowed
|
||||||
|
content-types and body.
|
||||||
|
_host_index (int/None): specifies the index of the server
|
||||||
|
that we want to use.
|
||||||
|
Default is read from the configuration.
|
||||||
|
async_req (bool): execute request asynchronously
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
ShamanSingleFileStatus
|
||||||
|
If the method is called asynchronously, returns the request
|
||||||
|
thread.
|
||||||
|
"""
|
||||||
|
kwargs['async_req'] = kwargs.get(
|
||||||
|
'async_req', False
|
||||||
|
)
|
||||||
|
kwargs['_return_http_data_only'] = kwargs.get(
|
||||||
|
'_return_http_data_only', True
|
||||||
|
)
|
||||||
|
kwargs['_preload_content'] = kwargs.get(
|
||||||
|
'_preload_content', True
|
||||||
|
)
|
||||||
|
kwargs['_request_timeout'] = kwargs.get(
|
||||||
|
'_request_timeout', None
|
||||||
|
)
|
||||||
|
kwargs['_check_input_type'] = kwargs.get(
|
||||||
|
'_check_input_type', True
|
||||||
|
)
|
||||||
|
kwargs['_check_return_type'] = kwargs.get(
|
||||||
|
'_check_return_type', True
|
||||||
|
)
|
||||||
|
kwargs['_spec_property_naming'] = kwargs.get(
|
||||||
|
'_spec_property_naming', False
|
||||||
|
)
|
||||||
|
kwargs['_content_type'] = kwargs.get(
|
||||||
|
'_content_type')
|
||||||
|
kwargs['_host_index'] = kwargs.get('_host_index')
|
||||||
|
kwargs['checksum'] = \
|
||||||
|
checksum
|
||||||
|
kwargs['filesize'] = \
|
||||||
|
filesize
|
||||||
|
return self.shaman_file_store_check_endpoint.call_with_http_info(**kwargs)
|
||||||
|
|
@ -76,7 +76,7 @@ class ApiClient(object):
|
|||||||
self.default_headers[header_name] = header_value
|
self.default_headers[header_name] = header_value
|
||||||
self.cookie = cookie
|
self.cookie = cookie
|
||||||
# Set default User-Agent.
|
# Set default User-Agent.
|
||||||
self.user_agent = 'Flamenco/7bfde1df-dirty (Blender add-on)'
|
self.user_agent = 'Flamenco/63793f42-dirty (Blender add-on)'
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
return self
|
return self
|
||||||
|
@ -16,4 +16,5 @@
|
|||||||
# Import APIs into API package:
|
# Import APIs into API package:
|
||||||
from flamenco.manager.api.jobs_api import JobsApi
|
from flamenco.manager.api.jobs_api import JobsApi
|
||||||
from flamenco.manager.api.meta_api import MetaApi
|
from flamenco.manager.api.meta_api import MetaApi
|
||||||
|
from flamenco.manager.api.shaman_api import ShamanApi
|
||||||
from flamenco.manager.api.worker_api import WorkerApi
|
from flamenco.manager.api.worker_api import WorkerApi
|
||||||
|
@ -404,7 +404,7 @@ conf = flamenco.manager.Configuration(
|
|||||||
"OS: {env}\n"\
|
"OS: {env}\n"\
|
||||||
"Python Version: {pyversion}\n"\
|
"Python Version: {pyversion}\n"\
|
||||||
"Version of the API: 1.0.0\n"\
|
"Version of the API: 1.0.0\n"\
|
||||||
"SDK Package Version: 7bfde1df-dirty".\
|
"SDK Package Version: 63793f42-dirty".\
|
||||||
format(env=sys.platform, pyversion=sys.version)
|
format(env=sys.platform, pyversion=sys.version)
|
||||||
|
|
||||||
def get_host_settings(self):
|
def get_host_settings(self):
|
||||||
|
318
addon/flamenco/manager/docs/ShamanApi.md
Normal file
318
addon/flamenco/manager/docs/ShamanApi.md
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
# flamenco.manager.ShamanApi
|
||||||
|
|
||||||
|
All URIs are relative to *http://localhost*
|
||||||
|
|
||||||
|
Method | HTTP request | Description
|
||||||
|
------------- | ------------- | -------------
|
||||||
|
[**shaman_checkout**](ShamanApi.md#shaman_checkout) | **POST** /shaman/checkout/create | Create a directory, and symlink the required files into it. The files must all have been uploaded to Shaman before calling this endpoint.
|
||||||
|
[**shaman_checkout_requirements**](ShamanApi.md#shaman_checkout_requirements) | **POST** /shaman/checkout/requirements | Checks a Shaman Requirements file, and reports which files are unknown.
|
||||||
|
[**shaman_file_store**](ShamanApi.md#shaman_file_store) | **POST** /shaman/files/{checksum}/{filesize} | Store a new file on the Shaman server. Note that the Shaman server can forcibly close the HTTP connection when another client finishes uploading the exact same file, to prevent double uploads. The file's contents should be sent in the request body.
|
||||||
|
[**shaman_file_store_check**](ShamanApi.md#shaman_file_store_check) | **OPTIONS** /shaman/files/{checksum}/{filesize} | Check the status of a file on the Shaman server.
|
||||||
|
|
||||||
|
|
||||||
|
# **shaman_checkout**
|
||||||
|
> shaman_checkout(shaman_checkout)
|
||||||
|
|
||||||
|
Create a directory, and symlink the required files into it. The files must all have been uploaded to Shaman before calling this endpoint.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
|
||||||
|
```python
|
||||||
|
import time
|
||||||
|
import flamenco.manager
|
||||||
|
from flamenco.manager.api import shaman_api
|
||||||
|
from flamenco.manager.model.error import Error
|
||||||
|
from flamenco.manager.model.shaman_checkout import ShamanCheckout
|
||||||
|
from pprint import pprint
|
||||||
|
# Defining the host is optional and defaults to http://localhost
|
||||||
|
# See configuration.py for a list of all supported configuration parameters.
|
||||||
|
configuration = flamenco.manager.Configuration(
|
||||||
|
host = "http://localhost"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Enter a context with an instance of the API client
|
||||||
|
with flamenco.manager.ApiClient() as api_client:
|
||||||
|
# Create an instance of the API class
|
||||||
|
api_instance = shaman_api.ShamanApi(api_client)
|
||||||
|
shaman_checkout = ShamanCheckout(
|
||||||
|
files=[
|
||||||
|
ShamanFileSpec(
|
||||||
|
sha="sha_example",
|
||||||
|
size=1,
|
||||||
|
path="path_example",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
checkout_path="checkout_path_example",
|
||||||
|
) # ShamanCheckout | Set of files to check out.
|
||||||
|
|
||||||
|
# example passing only required values which don't have defaults set
|
||||||
|
try:
|
||||||
|
# Create a directory, and symlink the required files into it. The files must all have been uploaded to Shaman before calling this endpoint.
|
||||||
|
api_instance.shaman_checkout(shaman_checkout)
|
||||||
|
except flamenco.manager.ApiException as e:
|
||||||
|
print("Exception when calling ShamanApi->shaman_checkout: %s\n" % e)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------- | ------------- | ------------- | -------------
|
||||||
|
**shaman_checkout** | [**ShamanCheckout**](ShamanCheckout.md)| Set of files to check out. |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
void (empty response body)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
No authorization required
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: application/json
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
|
||||||
|
### HTTP response details
|
||||||
|
|
||||||
|
| Status code | Description | Response headers |
|
||||||
|
|-------------|-------------|------------------|
|
||||||
|
**204** | Checkout was created succesfully. | - |
|
||||||
|
**424** | There were files missing. Use `shamanCheckoutRequirements` to figure out which ones. | - |
|
||||||
|
**409** | Checkout already exists. | - |
|
||||||
|
**0** | unexpected error | - |
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
# **shaman_checkout_requirements**
|
||||||
|
> ShamanRequirementsResponse shaman_checkout_requirements(shaman_requirements_request)
|
||||||
|
|
||||||
|
Checks a Shaman Requirements file, and reports which files are unknown.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
|
||||||
|
```python
|
||||||
|
import time
|
||||||
|
import flamenco.manager
|
||||||
|
from flamenco.manager.api import shaman_api
|
||||||
|
from flamenco.manager.model.shaman_requirements_request import ShamanRequirementsRequest
|
||||||
|
from flamenco.manager.model.error import Error
|
||||||
|
from flamenco.manager.model.shaman_requirements_response import ShamanRequirementsResponse
|
||||||
|
from pprint import pprint
|
||||||
|
# Defining the host is optional and defaults to http://localhost
|
||||||
|
# See configuration.py for a list of all supported configuration parameters.
|
||||||
|
configuration = flamenco.manager.Configuration(
|
||||||
|
host = "http://localhost"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Enter a context with an instance of the API client
|
||||||
|
with flamenco.manager.ApiClient() as api_client:
|
||||||
|
# Create an instance of the API class
|
||||||
|
api_instance = shaman_api.ShamanApi(api_client)
|
||||||
|
shaman_requirements_request = ShamanRequirementsRequest(
|
||||||
|
files=[
|
||||||
|
ShamanFileSpec(
|
||||||
|
sha="sha_example",
|
||||||
|
size=1,
|
||||||
|
path="path_example",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
) # ShamanRequirementsRequest | Set of files to check
|
||||||
|
|
||||||
|
# example passing only required values which don't have defaults set
|
||||||
|
try:
|
||||||
|
# Checks a Shaman Requirements file, and reports which files are unknown.
|
||||||
|
api_response = api_instance.shaman_checkout_requirements(shaman_requirements_request)
|
||||||
|
pprint(api_response)
|
||||||
|
except flamenco.manager.ApiException as e:
|
||||||
|
print("Exception when calling ShamanApi->shaman_checkout_requirements: %s\n" % e)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------- | ------------- | ------------- | -------------
|
||||||
|
**shaman_requirements_request** | [**ShamanRequirementsRequest**](ShamanRequirementsRequest.md)| Set of files to check |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**ShamanRequirementsResponse**](ShamanRequirementsResponse.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
No authorization required
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: application/json
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
|
||||||
|
### HTTP response details
|
||||||
|
|
||||||
|
| Status code | Description | Response headers |
|
||||||
|
|-------------|-------------|------------------|
|
||||||
|
**200** | Subset of the posted requirements, indicating the unknown files. | - |
|
||||||
|
**0** | unexpected error | - |
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
# **shaman_file_store**
|
||||||
|
> shaman_file_store(checksum, filesize, body)
|
||||||
|
|
||||||
|
Store a new file on the Shaman server. Note that the Shaman server can forcibly close the HTTP connection when another client finishes uploading the exact same file, to prevent double uploads. The file's contents should be sent in the request body.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
|
||||||
|
```python
|
||||||
|
import time
|
||||||
|
import flamenco.manager
|
||||||
|
from flamenco.manager.api import shaman_api
|
||||||
|
from flamenco.manager.model.error import Error
|
||||||
|
from pprint import pprint
|
||||||
|
# Defining the host is optional and defaults to http://localhost
|
||||||
|
# See configuration.py for a list of all supported configuration parameters.
|
||||||
|
configuration = flamenco.manager.Configuration(
|
||||||
|
host = "http://localhost"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Enter a context with an instance of the API client
|
||||||
|
with flamenco.manager.ApiClient() as api_client:
|
||||||
|
# Create an instance of the API class
|
||||||
|
api_instance = shaman_api.ShamanApi(api_client)
|
||||||
|
checksum = "checksum_example" # str | SHA256 checksum of the file.
|
||||||
|
filesize = 1 # int | Size of the file in bytes.
|
||||||
|
body = open('/path/to/file', 'rb') # file_type | Contents of the file
|
||||||
|
x_shaman_can_defer_upload = True # bool | The client indicates that it can defer uploading this file. The \"208\" response will not only be returned when the file is already fully known to the Shaman server, but also when someone else is currently uploading this file. (optional)
|
||||||
|
x_shaman_original_filename = "X-Shaman-Original-Filename_example" # str | The original filename. If sent along with the request, it will be included in the server logs, which can aid in debugging. (optional)
|
||||||
|
|
||||||
|
# example passing only required values which don't have defaults set
|
||||||
|
try:
|
||||||
|
# Store a new file on the Shaman server. Note that the Shaman server can forcibly close the HTTP connection when another client finishes uploading the exact same file, to prevent double uploads. The file's contents should be sent in the request body.
|
||||||
|
api_instance.shaman_file_store(checksum, filesize, body)
|
||||||
|
except flamenco.manager.ApiException as e:
|
||||||
|
print("Exception when calling ShamanApi->shaman_file_store: %s\n" % e)
|
||||||
|
|
||||||
|
# example passing only required values which don't have defaults set
|
||||||
|
# and optional values
|
||||||
|
try:
|
||||||
|
# Store a new file on the Shaman server. Note that the Shaman server can forcibly close the HTTP connection when another client finishes uploading the exact same file, to prevent double uploads. The file's contents should be sent in the request body.
|
||||||
|
api_instance.shaman_file_store(checksum, filesize, body, x_shaman_can_defer_upload=x_shaman_can_defer_upload, x_shaman_original_filename=x_shaman_original_filename)
|
||||||
|
except flamenco.manager.ApiException as e:
|
||||||
|
print("Exception when calling ShamanApi->shaman_file_store: %s\n" % e)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------- | ------------- | ------------- | -------------
|
||||||
|
**checksum** | **str**| SHA256 checksum of the file. |
|
||||||
|
**filesize** | **int**| Size of the file in bytes. |
|
||||||
|
**body** | **file_type**| Contents of the file |
|
||||||
|
**x_shaman_can_defer_upload** | **bool**| The client indicates that it can defer uploading this file. The \"208\" response will not only be returned when the file is already fully known to the Shaman server, but also when someone else is currently uploading this file. | [optional]
|
||||||
|
**x_shaman_original_filename** | **str**| The original filename. If sent along with the request, it will be included in the server logs, which can aid in debugging. | [optional]
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
void (empty response body)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
No authorization required
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: application/octet-stream
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
|
||||||
|
### HTTP response details
|
||||||
|
|
||||||
|
| Status code | Description | Response headers |
|
||||||
|
|-------------|-------------|------------------|
|
||||||
|
**204** | The file was accepted. | - |
|
||||||
|
**208** | The file was already known to the server. | - |
|
||||||
|
**417** | There was a mismatch between the request parameters and the actual file size or checksum of the uploaded file. | - |
|
||||||
|
**425** | Client should defer uploading this file. The file is currently in the process of being uploaded by someone else, and `X-Shaman-Can-Defer-Upload: true` was sent in the request. | - |
|
||||||
|
**0** | unexpected error | - |
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
# **shaman_file_store_check**
|
||||||
|
> ShamanSingleFileStatus shaman_file_store_check(checksum, filesize)
|
||||||
|
|
||||||
|
Check the status of a file on the Shaman server.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
|
||||||
|
```python
|
||||||
|
import time
|
||||||
|
import flamenco.manager
|
||||||
|
from flamenco.manager.api import shaman_api
|
||||||
|
from flamenco.manager.model.error import Error
|
||||||
|
from flamenco.manager.model.shaman_single_file_status import ShamanSingleFileStatus
|
||||||
|
from pprint import pprint
|
||||||
|
# Defining the host is optional and defaults to http://localhost
|
||||||
|
# See configuration.py for a list of all supported configuration parameters.
|
||||||
|
configuration = flamenco.manager.Configuration(
|
||||||
|
host = "http://localhost"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Enter a context with an instance of the API client
|
||||||
|
with flamenco.manager.ApiClient() as api_client:
|
||||||
|
# Create an instance of the API class
|
||||||
|
api_instance = shaman_api.ShamanApi(api_client)
|
||||||
|
checksum = "checksum_example" # str | SHA256 checksum of the file.
|
||||||
|
filesize = 1 # int | Size of the file in bytes.
|
||||||
|
|
||||||
|
# example passing only required values which don't have defaults set
|
||||||
|
try:
|
||||||
|
# Check the status of a file on the Shaman server.
|
||||||
|
api_response = api_instance.shaman_file_store_check(checksum, filesize)
|
||||||
|
pprint(api_response)
|
||||||
|
except flamenco.manager.ApiException as e:
|
||||||
|
print("Exception when calling ShamanApi->shaman_file_store_check: %s\n" % e)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------- | ------------- | ------------- | -------------
|
||||||
|
**checksum** | **str**| SHA256 checksum of the file. |
|
||||||
|
**filesize** | **int**| Size of the file in bytes. |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**ShamanSingleFileStatus**](ShamanSingleFileStatus.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
No authorization required
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: Not defined
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
|
||||||
|
### HTTP response details
|
||||||
|
|
||||||
|
| Status code | Description | Response headers |
|
||||||
|
|-------------|-------------|------------------|
|
||||||
|
**200** | Normal response. | - |
|
||||||
|
**0** | unexpected error | - |
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
14
addon/flamenco/manager/docs/ShamanCheckout.md
Normal file
14
addon/flamenco/manager/docs/ShamanCheckout.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# ShamanCheckout
|
||||||
|
|
||||||
|
Set of files with their SHA256 checksum, size in bytes, and desired location in the checkout directory.
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**files** | [**[ShamanFileSpec]**](ShamanFileSpec.md) | |
|
||||||
|
**checkout_path** | **str** | Path where the Manager should create this checkout, It is relative to the Shaman checkout path as configured on the Manager. In older versions of the Shaman this was just the \"checkout ID\", but in this version it can be a path like `project-slug/scene-name/unique-ID`. |
|
||||||
|
**any string name** | **bool, date, datetime, dict, float, int, list, str, none_type** | any string name can be used but the value must be the correct type | [optional]
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
15
addon/flamenco/manager/docs/ShamanFileSpec.md
Normal file
15
addon/flamenco/manager/docs/ShamanFileSpec.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# ShamanFileSpec
|
||||||
|
|
||||||
|
Specification of a file in the Shaman storage.
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**sha** | **str** | SHA256 checksum of the file |
|
||||||
|
**size** | **int** | File size in bytes |
|
||||||
|
**path** | **str** | Location of the file in the checkout |
|
||||||
|
**any string name** | **bool, date, datetime, dict, float, int, list, str, none_type** | any string name can be used but the value must be the correct type | [optional]
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
15
addon/flamenco/manager/docs/ShamanFileSpecWithStatus.md
Normal file
15
addon/flamenco/manager/docs/ShamanFileSpecWithStatus.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# ShamanFileSpecWithStatus
|
||||||
|
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**sha** | **str** | SHA256 checksum of the file |
|
||||||
|
**size** | **int** | File size in bytes |
|
||||||
|
**path** | **str** | Location of the file in the checkout |
|
||||||
|
**status** | [**ShamanFileStatus**](ShamanFileStatus.md) | |
|
||||||
|
**any string name** | **bool, date, datetime, dict, float, int, list, str, none_type** | any string name can be used but the value must be the correct type | [optional]
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
12
addon/flamenco/manager/docs/ShamanFileSpecWithStatusAllOf.md
Normal file
12
addon/flamenco/manager/docs/ShamanFileSpecWithStatusAllOf.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# ShamanFileSpecWithStatusAllOf
|
||||||
|
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**status** | [**ShamanFileStatus**](ShamanFileStatus.md) | |
|
||||||
|
**any string name** | **bool, date, datetime, dict, float, int, list, str, none_type** | any string name can be used but the value must be the correct type | [optional]
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
11
addon/flamenco/manager/docs/ShamanFileStatus.md
Normal file
11
addon/flamenco/manager/docs/ShamanFileStatus.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# ShamanFileStatus
|
||||||
|
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**value** | **str** | | must be one of ["unknown", "uploading", "stored", ]
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
13
addon/flamenco/manager/docs/ShamanRequirementsRequest.md
Normal file
13
addon/flamenco/manager/docs/ShamanRequirementsRequest.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# ShamanRequirementsRequest
|
||||||
|
|
||||||
|
Set of files with their SHA256 checksum and size in bytes.
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**files** | [**[ShamanFileSpec]**](ShamanFileSpec.md) | |
|
||||||
|
**any string name** | **bool, date, datetime, dict, float, int, list, str, none_type** | any string name can be used but the value must be the correct type | [optional]
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
13
addon/flamenco/manager/docs/ShamanRequirementsResponse.md
Normal file
13
addon/flamenco/manager/docs/ShamanRequirementsResponse.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# ShamanRequirementsResponse
|
||||||
|
|
||||||
|
The files from a requirements request, with their status on the Shaman server. Files that are known to Shaman are excluded from the response.
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**files** | [**[ShamanFileSpecWithStatus]**](ShamanFileSpecWithStatus.md) | |
|
||||||
|
**any string name** | **bool, date, datetime, dict, float, int, list, str, none_type** | any string name can be used but the value must be the correct type | [optional]
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
13
addon/flamenco/manager/docs/ShamanSingleFileStatus.md
Normal file
13
addon/flamenco/manager/docs/ShamanSingleFileStatus.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# ShamanSingleFileStatus
|
||||||
|
|
||||||
|
Status of a file in the Shaman storage.
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**status** | [**ShamanFileStatus**](ShamanFileStatus.md) | |
|
||||||
|
**any string name** | **bool, date, datetime, dict, float, int, list, str, none_type** | any string name can be used but the value must be the correct type | [optional]
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
273
addon/flamenco/manager/model/shaman_checkout.py
Normal file
273
addon/flamenco/manager/model/shaman_checkout.py
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
"""
|
||||||
|
Flamenco manager
|
||||||
|
|
||||||
|
Render Farm manager API # noqa: E501
|
||||||
|
|
||||||
|
The version of the OpenAPI document: 1.0.0
|
||||||
|
Generated by: https://openapi-generator.tech
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import re # noqa: F401
|
||||||
|
import sys # noqa: F401
|
||||||
|
|
||||||
|
from flamenco.manager.model_utils import ( # noqa: F401
|
||||||
|
ApiTypeError,
|
||||||
|
ModelComposed,
|
||||||
|
ModelNormal,
|
||||||
|
ModelSimple,
|
||||||
|
cached_property,
|
||||||
|
change_keys_js_to_python,
|
||||||
|
convert_js_args_to_python_args,
|
||||||
|
date,
|
||||||
|
datetime,
|
||||||
|
file_type,
|
||||||
|
none_type,
|
||||||
|
validate_get_composed_info,
|
||||||
|
OpenApiModel
|
||||||
|
)
|
||||||
|
from flamenco.manager.exceptions import ApiAttributeError
|
||||||
|
|
||||||
|
|
||||||
|
def lazy_import():
|
||||||
|
from flamenco.manager.model.shaman_file_spec import ShamanFileSpec
|
||||||
|
globals()['ShamanFileSpec'] = ShamanFileSpec
|
||||||
|
|
||||||
|
|
||||||
|
class ShamanCheckout(ModelNormal):
|
||||||
|
"""NOTE: This class is auto generated by OpenAPI Generator.
|
||||||
|
Ref: https://openapi-generator.tech
|
||||||
|
|
||||||
|
Do not edit the class manually.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
allowed_values (dict): The key is the tuple path to the attribute
|
||||||
|
and the for var_name this is (var_name,). The value is a dict
|
||||||
|
with a capitalized key describing the allowed value and an allowed
|
||||||
|
value. These dicts store the allowed enum values.
|
||||||
|
attribute_map (dict): The key is attribute name
|
||||||
|
and the value is json key in definition.
|
||||||
|
discriminator_value_class_map (dict): A dict to go from the discriminator
|
||||||
|
variable value to the discriminator class name.
|
||||||
|
validations (dict): The key is the tuple path to the attribute
|
||||||
|
and the for var_name this is (var_name,). The value is a dict
|
||||||
|
that stores validations for max_length, min_length, max_items,
|
||||||
|
min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum,
|
||||||
|
inclusive_minimum, and regex.
|
||||||
|
additional_properties_type (tuple): A tuple of classes accepted
|
||||||
|
as additional properties values.
|
||||||
|
"""
|
||||||
|
|
||||||
|
allowed_values = {
|
||||||
|
}
|
||||||
|
|
||||||
|
validations = {
|
||||||
|
}
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def additional_properties_type():
|
||||||
|
"""
|
||||||
|
This must be a method because a model may have properties that are
|
||||||
|
of type self, this must run after the class is loaded
|
||||||
|
"""
|
||||||
|
lazy_import()
|
||||||
|
return (bool, date, datetime, dict, float, int, list, str, none_type,) # noqa: E501
|
||||||
|
|
||||||
|
_nullable = False
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def openapi_types():
|
||||||
|
"""
|
||||||
|
This must be a method because a model may have properties that are
|
||||||
|
of type self, this must run after the class is loaded
|
||||||
|
|
||||||
|
Returns
|
||||||
|
openapi_types (dict): The key is attribute name
|
||||||
|
and the value is attribute type.
|
||||||
|
"""
|
||||||
|
lazy_import()
|
||||||
|
return {
|
||||||
|
'files': ([ShamanFileSpec],), # noqa: E501
|
||||||
|
'checkout_path': (str,), # noqa: E501
|
||||||
|
}
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def discriminator():
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
attribute_map = {
|
||||||
|
'files': 'files', # noqa: E501
|
||||||
|
'checkout_path': 'checkoutPath', # noqa: E501
|
||||||
|
}
|
||||||
|
|
||||||
|
read_only_vars = {
|
||||||
|
}
|
||||||
|
|
||||||
|
_composed_schemas = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@convert_js_args_to_python_args
|
||||||
|
def _from_openapi_data(cls, files, checkout_path, *args, **kwargs): # noqa: E501
|
||||||
|
"""ShamanCheckout - a model defined in OpenAPI
|
||||||
|
|
||||||
|
Args:
|
||||||
|
files ([ShamanFileSpec]):
|
||||||
|
checkout_path (str): Path where the Manager should create this checkout, It is relative to the Shaman checkout path as configured on the Manager. In older versions of the Shaman this was just the \"checkout ID\", but in this version it can be a path like `project-slug/scene-name/unique-ID`.
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
_check_type (bool): if True, values for parameters in openapi_types
|
||||||
|
will be type checked and a TypeError will be
|
||||||
|
raised if the wrong type is input.
|
||||||
|
Defaults to True
|
||||||
|
_path_to_item (tuple/list): This is a list of keys or values to
|
||||||
|
drill down to the model in received_data
|
||||||
|
when deserializing a response
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_configuration (Configuration): the instance to use when
|
||||||
|
deserializing a file_type parameter.
|
||||||
|
If passed, type conversion is attempted
|
||||||
|
If omitted no type conversion is done.
|
||||||
|
_visited_composed_classes (tuple): This stores a tuple of
|
||||||
|
classes that we have traveled through so that
|
||||||
|
if we see that class again we will not use its
|
||||||
|
discriminator again.
|
||||||
|
When traveling through a discriminator, the
|
||||||
|
composed schema that is
|
||||||
|
is traveled through is added to this set.
|
||||||
|
For example if Animal has a discriminator
|
||||||
|
petType and we pass in "Dog", and the class Dog
|
||||||
|
allOf includes Animal, we move through Animal
|
||||||
|
once using the discriminator, and pick Dog.
|
||||||
|
Then in Dog, we will make an instance of the
|
||||||
|
Animal class but this time we won't travel
|
||||||
|
through its discriminator because we passed in
|
||||||
|
_visited_composed_classes = (Animal,)
|
||||||
|
"""
|
||||||
|
|
||||||
|
_check_type = kwargs.pop('_check_type', True)
|
||||||
|
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||||
|
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||||
|
_configuration = kwargs.pop('_configuration', None)
|
||||||
|
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
|
||||||
|
|
||||||
|
self = super(OpenApiModel, cls).__new__(cls)
|
||||||
|
|
||||||
|
if args:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
|
||||||
|
args,
|
||||||
|
self.__class__.__name__,
|
||||||
|
),
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
self._data_store = {}
|
||||||
|
self._check_type = _check_type
|
||||||
|
self._spec_property_naming = _spec_property_naming
|
||||||
|
self._path_to_item = _path_to_item
|
||||||
|
self._configuration = _configuration
|
||||||
|
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||||
|
|
||||||
|
self.files = files
|
||||||
|
self.checkout_path = checkout_path
|
||||||
|
for var_name, var_value in kwargs.items():
|
||||||
|
if var_name not in self.attribute_map and \
|
||||||
|
self._configuration is not None and \
|
||||||
|
self._configuration.discard_unknown_keys and \
|
||||||
|
self.additional_properties_type is None:
|
||||||
|
# discard variable.
|
||||||
|
continue
|
||||||
|
setattr(self, var_name, var_value)
|
||||||
|
return self
|
||||||
|
|
||||||
|
required_properties = set([
|
||||||
|
'_data_store',
|
||||||
|
'_check_type',
|
||||||
|
'_spec_property_naming',
|
||||||
|
'_path_to_item',
|
||||||
|
'_configuration',
|
||||||
|
'_visited_composed_classes',
|
||||||
|
])
|
||||||
|
|
||||||
|
@convert_js_args_to_python_args
|
||||||
|
def __init__(self, files, checkout_path, *args, **kwargs): # noqa: E501
|
||||||
|
"""ShamanCheckout - a model defined in OpenAPI
|
||||||
|
|
||||||
|
Args:
|
||||||
|
files ([ShamanFileSpec]):
|
||||||
|
checkout_path (str): Path where the Manager should create this checkout, It is relative to the Shaman checkout path as configured on the Manager. In older versions of the Shaman this was just the \"checkout ID\", but in this version it can be a path like `project-slug/scene-name/unique-ID`.
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
_check_type (bool): if True, values for parameters in openapi_types
|
||||||
|
will be type checked and a TypeError will be
|
||||||
|
raised if the wrong type is input.
|
||||||
|
Defaults to True
|
||||||
|
_path_to_item (tuple/list): This is a list of keys or values to
|
||||||
|
drill down to the model in received_data
|
||||||
|
when deserializing a response
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_configuration (Configuration): the instance to use when
|
||||||
|
deserializing a file_type parameter.
|
||||||
|
If passed, type conversion is attempted
|
||||||
|
If omitted no type conversion is done.
|
||||||
|
_visited_composed_classes (tuple): This stores a tuple of
|
||||||
|
classes that we have traveled through so that
|
||||||
|
if we see that class again we will not use its
|
||||||
|
discriminator again.
|
||||||
|
When traveling through a discriminator, the
|
||||||
|
composed schema that is
|
||||||
|
is traveled through is added to this set.
|
||||||
|
For example if Animal has a discriminator
|
||||||
|
petType and we pass in "Dog", and the class Dog
|
||||||
|
allOf includes Animal, we move through Animal
|
||||||
|
once using the discriminator, and pick Dog.
|
||||||
|
Then in Dog, we will make an instance of the
|
||||||
|
Animal class but this time we won't travel
|
||||||
|
through its discriminator because we passed in
|
||||||
|
_visited_composed_classes = (Animal,)
|
||||||
|
"""
|
||||||
|
|
||||||
|
_check_type = kwargs.pop('_check_type', True)
|
||||||
|
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||||
|
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||||
|
_configuration = kwargs.pop('_configuration', None)
|
||||||
|
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
|
||||||
|
|
||||||
|
if args:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
|
||||||
|
args,
|
||||||
|
self.__class__.__name__,
|
||||||
|
),
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
self._data_store = {}
|
||||||
|
self._check_type = _check_type
|
||||||
|
self._spec_property_naming = _spec_property_naming
|
||||||
|
self._path_to_item = _path_to_item
|
||||||
|
self._configuration = _configuration
|
||||||
|
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||||
|
|
||||||
|
self.files = files
|
||||||
|
self.checkout_path = checkout_path
|
||||||
|
for var_name, var_value in kwargs.items():
|
||||||
|
if var_name not in self.attribute_map and \
|
||||||
|
self._configuration is not None and \
|
||||||
|
self._configuration.discard_unknown_keys and \
|
||||||
|
self.additional_properties_type is None:
|
||||||
|
# discard variable.
|
||||||
|
continue
|
||||||
|
setattr(self, var_name, var_value)
|
||||||
|
if var_name in self.read_only_vars:
|
||||||
|
raise ApiAttributeError(f"`{var_name}` is a read-only attribute. Use `from_openapi_data` to instantiate "
|
||||||
|
f"class with read only attributes.")
|
273
addon/flamenco/manager/model/shaman_file_spec.py
Normal file
273
addon/flamenco/manager/model/shaman_file_spec.py
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
"""
|
||||||
|
Flamenco manager
|
||||||
|
|
||||||
|
Render Farm manager API # noqa: E501
|
||||||
|
|
||||||
|
The version of the OpenAPI document: 1.0.0
|
||||||
|
Generated by: https://openapi-generator.tech
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import re # noqa: F401
|
||||||
|
import sys # noqa: F401
|
||||||
|
|
||||||
|
from flamenco.manager.model_utils import ( # noqa: F401
|
||||||
|
ApiTypeError,
|
||||||
|
ModelComposed,
|
||||||
|
ModelNormal,
|
||||||
|
ModelSimple,
|
||||||
|
cached_property,
|
||||||
|
change_keys_js_to_python,
|
||||||
|
convert_js_args_to_python_args,
|
||||||
|
date,
|
||||||
|
datetime,
|
||||||
|
file_type,
|
||||||
|
none_type,
|
||||||
|
validate_get_composed_info,
|
||||||
|
OpenApiModel
|
||||||
|
)
|
||||||
|
from flamenco.manager.exceptions import ApiAttributeError
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ShamanFileSpec(ModelNormal):
|
||||||
|
"""NOTE: This class is auto generated by OpenAPI Generator.
|
||||||
|
Ref: https://openapi-generator.tech
|
||||||
|
|
||||||
|
Do not edit the class manually.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
allowed_values (dict): The key is the tuple path to the attribute
|
||||||
|
and the for var_name this is (var_name,). The value is a dict
|
||||||
|
with a capitalized key describing the allowed value and an allowed
|
||||||
|
value. These dicts store the allowed enum values.
|
||||||
|
attribute_map (dict): The key is attribute name
|
||||||
|
and the value is json key in definition.
|
||||||
|
discriminator_value_class_map (dict): A dict to go from the discriminator
|
||||||
|
variable value to the discriminator class name.
|
||||||
|
validations (dict): The key is the tuple path to the attribute
|
||||||
|
and the for var_name this is (var_name,). The value is a dict
|
||||||
|
that stores validations for max_length, min_length, max_items,
|
||||||
|
min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum,
|
||||||
|
inclusive_minimum, and regex.
|
||||||
|
additional_properties_type (tuple): A tuple of classes accepted
|
||||||
|
as additional properties values.
|
||||||
|
"""
|
||||||
|
|
||||||
|
allowed_values = {
|
||||||
|
}
|
||||||
|
|
||||||
|
validations = {
|
||||||
|
}
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def additional_properties_type():
|
||||||
|
"""
|
||||||
|
This must be a method because a model may have properties that are
|
||||||
|
of type self, this must run after the class is loaded
|
||||||
|
"""
|
||||||
|
return (bool, date, datetime, dict, float, int, list, str, none_type,) # noqa: E501
|
||||||
|
|
||||||
|
_nullable = False
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def openapi_types():
|
||||||
|
"""
|
||||||
|
This must be a method because a model may have properties that are
|
||||||
|
of type self, this must run after the class is loaded
|
||||||
|
|
||||||
|
Returns
|
||||||
|
openapi_types (dict): The key is attribute name
|
||||||
|
and the value is attribute type.
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
'sha': (str,), # noqa: E501
|
||||||
|
'size': (int,), # noqa: E501
|
||||||
|
'path': (str,), # noqa: E501
|
||||||
|
}
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def discriminator():
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
attribute_map = {
|
||||||
|
'sha': 'sha', # noqa: E501
|
||||||
|
'size': 'size', # noqa: E501
|
||||||
|
'path': 'path', # noqa: E501
|
||||||
|
}
|
||||||
|
|
||||||
|
read_only_vars = {
|
||||||
|
}
|
||||||
|
|
||||||
|
_composed_schemas = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@convert_js_args_to_python_args
|
||||||
|
def _from_openapi_data(cls, sha, size, path, *args, **kwargs): # noqa: E501
|
||||||
|
"""ShamanFileSpec - a model defined in OpenAPI
|
||||||
|
|
||||||
|
Args:
|
||||||
|
sha (str): SHA256 checksum of the file
|
||||||
|
size (int): File size in bytes
|
||||||
|
path (str): Location of the file in the checkout
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
_check_type (bool): if True, values for parameters in openapi_types
|
||||||
|
will be type checked and a TypeError will be
|
||||||
|
raised if the wrong type is input.
|
||||||
|
Defaults to True
|
||||||
|
_path_to_item (tuple/list): This is a list of keys or values to
|
||||||
|
drill down to the model in received_data
|
||||||
|
when deserializing a response
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_configuration (Configuration): the instance to use when
|
||||||
|
deserializing a file_type parameter.
|
||||||
|
If passed, type conversion is attempted
|
||||||
|
If omitted no type conversion is done.
|
||||||
|
_visited_composed_classes (tuple): This stores a tuple of
|
||||||
|
classes that we have traveled through so that
|
||||||
|
if we see that class again we will not use its
|
||||||
|
discriminator again.
|
||||||
|
When traveling through a discriminator, the
|
||||||
|
composed schema that is
|
||||||
|
is traveled through is added to this set.
|
||||||
|
For example if Animal has a discriminator
|
||||||
|
petType and we pass in "Dog", and the class Dog
|
||||||
|
allOf includes Animal, we move through Animal
|
||||||
|
once using the discriminator, and pick Dog.
|
||||||
|
Then in Dog, we will make an instance of the
|
||||||
|
Animal class but this time we won't travel
|
||||||
|
through its discriminator because we passed in
|
||||||
|
_visited_composed_classes = (Animal,)
|
||||||
|
"""
|
||||||
|
|
||||||
|
_check_type = kwargs.pop('_check_type', True)
|
||||||
|
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||||
|
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||||
|
_configuration = kwargs.pop('_configuration', None)
|
||||||
|
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
|
||||||
|
|
||||||
|
self = super(OpenApiModel, cls).__new__(cls)
|
||||||
|
|
||||||
|
if args:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
|
||||||
|
args,
|
||||||
|
self.__class__.__name__,
|
||||||
|
),
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
self._data_store = {}
|
||||||
|
self._check_type = _check_type
|
||||||
|
self._spec_property_naming = _spec_property_naming
|
||||||
|
self._path_to_item = _path_to_item
|
||||||
|
self._configuration = _configuration
|
||||||
|
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||||
|
|
||||||
|
self.sha = sha
|
||||||
|
self.size = size
|
||||||
|
self.path = path
|
||||||
|
for var_name, var_value in kwargs.items():
|
||||||
|
if var_name not in self.attribute_map and \
|
||||||
|
self._configuration is not None and \
|
||||||
|
self._configuration.discard_unknown_keys and \
|
||||||
|
self.additional_properties_type is None:
|
||||||
|
# discard variable.
|
||||||
|
continue
|
||||||
|
setattr(self, var_name, var_value)
|
||||||
|
return self
|
||||||
|
|
||||||
|
required_properties = set([
|
||||||
|
'_data_store',
|
||||||
|
'_check_type',
|
||||||
|
'_spec_property_naming',
|
||||||
|
'_path_to_item',
|
||||||
|
'_configuration',
|
||||||
|
'_visited_composed_classes',
|
||||||
|
])
|
||||||
|
|
||||||
|
@convert_js_args_to_python_args
|
||||||
|
def __init__(self, sha, size, path, *args, **kwargs): # noqa: E501
|
||||||
|
"""ShamanFileSpec - a model defined in OpenAPI
|
||||||
|
|
||||||
|
Args:
|
||||||
|
sha (str): SHA256 checksum of the file
|
||||||
|
size (int): File size in bytes
|
||||||
|
path (str): Location of the file in the checkout
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
_check_type (bool): if True, values for parameters in openapi_types
|
||||||
|
will be type checked and a TypeError will be
|
||||||
|
raised if the wrong type is input.
|
||||||
|
Defaults to True
|
||||||
|
_path_to_item (tuple/list): This is a list of keys or values to
|
||||||
|
drill down to the model in received_data
|
||||||
|
when deserializing a response
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_configuration (Configuration): the instance to use when
|
||||||
|
deserializing a file_type parameter.
|
||||||
|
If passed, type conversion is attempted
|
||||||
|
If omitted no type conversion is done.
|
||||||
|
_visited_composed_classes (tuple): This stores a tuple of
|
||||||
|
classes that we have traveled through so that
|
||||||
|
if we see that class again we will not use its
|
||||||
|
discriminator again.
|
||||||
|
When traveling through a discriminator, the
|
||||||
|
composed schema that is
|
||||||
|
is traveled through is added to this set.
|
||||||
|
For example if Animal has a discriminator
|
||||||
|
petType and we pass in "Dog", and the class Dog
|
||||||
|
allOf includes Animal, we move through Animal
|
||||||
|
once using the discriminator, and pick Dog.
|
||||||
|
Then in Dog, we will make an instance of the
|
||||||
|
Animal class but this time we won't travel
|
||||||
|
through its discriminator because we passed in
|
||||||
|
_visited_composed_classes = (Animal,)
|
||||||
|
"""
|
||||||
|
|
||||||
|
_check_type = kwargs.pop('_check_type', True)
|
||||||
|
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||||
|
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||||
|
_configuration = kwargs.pop('_configuration', None)
|
||||||
|
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
|
||||||
|
|
||||||
|
if args:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
|
||||||
|
args,
|
||||||
|
self.__class__.__name__,
|
||||||
|
),
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
self._data_store = {}
|
||||||
|
self._check_type = _check_type
|
||||||
|
self._spec_property_naming = _spec_property_naming
|
||||||
|
self._path_to_item = _path_to_item
|
||||||
|
self._configuration = _configuration
|
||||||
|
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||||
|
|
||||||
|
self.sha = sha
|
||||||
|
self.size = size
|
||||||
|
self.path = path
|
||||||
|
for var_name, var_value in kwargs.items():
|
||||||
|
if var_name not in self.attribute_map and \
|
||||||
|
self._configuration is not None and \
|
||||||
|
self._configuration.discard_unknown_keys and \
|
||||||
|
self.additional_properties_type is None:
|
||||||
|
# discard variable.
|
||||||
|
continue
|
||||||
|
setattr(self, var_name, var_value)
|
||||||
|
if var_name in self.read_only_vars:
|
||||||
|
raise ApiAttributeError(f"`{var_name}` is a read-only attribute. Use `from_openapi_data` to instantiate "
|
||||||
|
f"class with read only attributes.")
|
328
addon/flamenco/manager/model/shaman_file_spec_with_status.py
Normal file
328
addon/flamenco/manager/model/shaman_file_spec_with_status.py
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
"""
|
||||||
|
Flamenco manager
|
||||||
|
|
||||||
|
Render Farm manager API # noqa: E501
|
||||||
|
|
||||||
|
The version of the OpenAPI document: 1.0.0
|
||||||
|
Generated by: https://openapi-generator.tech
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import re # noqa: F401
|
||||||
|
import sys # noqa: F401
|
||||||
|
|
||||||
|
from flamenco.manager.model_utils import ( # noqa: F401
|
||||||
|
ApiTypeError,
|
||||||
|
ModelComposed,
|
||||||
|
ModelNormal,
|
||||||
|
ModelSimple,
|
||||||
|
cached_property,
|
||||||
|
change_keys_js_to_python,
|
||||||
|
convert_js_args_to_python_args,
|
||||||
|
date,
|
||||||
|
datetime,
|
||||||
|
file_type,
|
||||||
|
none_type,
|
||||||
|
validate_get_composed_info,
|
||||||
|
OpenApiModel
|
||||||
|
)
|
||||||
|
from flamenco.manager.exceptions import ApiAttributeError
|
||||||
|
|
||||||
|
|
||||||
|
def lazy_import():
|
||||||
|
from flamenco.manager.model.shaman_file_spec import ShamanFileSpec
|
||||||
|
from flamenco.manager.model.shaman_file_spec_with_status_all_of import ShamanFileSpecWithStatusAllOf
|
||||||
|
from flamenco.manager.model.shaman_file_status import ShamanFileStatus
|
||||||
|
globals()['ShamanFileSpec'] = ShamanFileSpec
|
||||||
|
globals()['ShamanFileSpecWithStatusAllOf'] = ShamanFileSpecWithStatusAllOf
|
||||||
|
globals()['ShamanFileStatus'] = ShamanFileStatus
|
||||||
|
|
||||||
|
|
||||||
|
class ShamanFileSpecWithStatus(ModelComposed):
|
||||||
|
"""NOTE: This class is auto generated by OpenAPI Generator.
|
||||||
|
Ref: https://openapi-generator.tech
|
||||||
|
|
||||||
|
Do not edit the class manually.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
allowed_values (dict): The key is the tuple path to the attribute
|
||||||
|
and the for var_name this is (var_name,). The value is a dict
|
||||||
|
with a capitalized key describing the allowed value and an allowed
|
||||||
|
value. These dicts store the allowed enum values.
|
||||||
|
attribute_map (dict): The key is attribute name
|
||||||
|
and the value is json key in definition.
|
||||||
|
discriminator_value_class_map (dict): A dict to go from the discriminator
|
||||||
|
variable value to the discriminator class name.
|
||||||
|
validations (dict): The key is the tuple path to the attribute
|
||||||
|
and the for var_name this is (var_name,). The value is a dict
|
||||||
|
that stores validations for max_length, min_length, max_items,
|
||||||
|
min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum,
|
||||||
|
inclusive_minimum, and regex.
|
||||||
|
additional_properties_type (tuple): A tuple of classes accepted
|
||||||
|
as additional properties values.
|
||||||
|
"""
|
||||||
|
|
||||||
|
allowed_values = {
|
||||||
|
}
|
||||||
|
|
||||||
|
validations = {
|
||||||
|
}
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def additional_properties_type():
|
||||||
|
"""
|
||||||
|
This must be a method because a model may have properties that are
|
||||||
|
of type self, this must run after the class is loaded
|
||||||
|
"""
|
||||||
|
lazy_import()
|
||||||
|
return (bool, date, datetime, dict, float, int, list, str, none_type,) # noqa: E501
|
||||||
|
|
||||||
|
_nullable = False
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def openapi_types():
|
||||||
|
"""
|
||||||
|
This must be a method because a model may have properties that are
|
||||||
|
of type self, this must run after the class is loaded
|
||||||
|
|
||||||
|
Returns
|
||||||
|
openapi_types (dict): The key is attribute name
|
||||||
|
and the value is attribute type.
|
||||||
|
"""
|
||||||
|
lazy_import()
|
||||||
|
return {
|
||||||
|
'sha': (str,), # noqa: E501
|
||||||
|
'size': (int,), # noqa: E501
|
||||||
|
'path': (str,), # noqa: E501
|
||||||
|
'status': (ShamanFileStatus,), # noqa: E501
|
||||||
|
}
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def discriminator():
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
attribute_map = {
|
||||||
|
'sha': 'sha', # noqa: E501
|
||||||
|
'size': 'size', # noqa: E501
|
||||||
|
'path': 'path', # noqa: E501
|
||||||
|
'status': 'status', # noqa: E501
|
||||||
|
}
|
||||||
|
|
||||||
|
read_only_vars = {
|
||||||
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@convert_js_args_to_python_args
|
||||||
|
def _from_openapi_data(cls, *args, **kwargs): # noqa: E501
|
||||||
|
"""ShamanFileSpecWithStatus - a model defined in OpenAPI
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
sha (str): SHA256 checksum of the file
|
||||||
|
size (int): File size in bytes
|
||||||
|
path (str): Location of the file in the checkout
|
||||||
|
status (ShamanFileStatus):
|
||||||
|
_check_type (bool): if True, values for parameters in openapi_types
|
||||||
|
will be type checked and a TypeError will be
|
||||||
|
raised if the wrong type is input.
|
||||||
|
Defaults to True
|
||||||
|
_path_to_item (tuple/list): This is a list of keys or values to
|
||||||
|
drill down to the model in received_data
|
||||||
|
when deserializing a response
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_configuration (Configuration): the instance to use when
|
||||||
|
deserializing a file_type parameter.
|
||||||
|
If passed, type conversion is attempted
|
||||||
|
If omitted no type conversion is done.
|
||||||
|
_visited_composed_classes (tuple): This stores a tuple of
|
||||||
|
classes that we have traveled through so that
|
||||||
|
if we see that class again we will not use its
|
||||||
|
discriminator again.
|
||||||
|
When traveling through a discriminator, the
|
||||||
|
composed schema that is
|
||||||
|
is traveled through is added to this set.
|
||||||
|
For example if Animal has a discriminator
|
||||||
|
petType and we pass in "Dog", and the class Dog
|
||||||
|
allOf includes Animal, we move through Animal
|
||||||
|
once using the discriminator, and pick Dog.
|
||||||
|
Then in Dog, we will make an instance of the
|
||||||
|
Animal class but this time we won't travel
|
||||||
|
through its discriminator because we passed in
|
||||||
|
_visited_composed_classes = (Animal,)
|
||||||
|
"""
|
||||||
|
|
||||||
|
_check_type = kwargs.pop('_check_type', True)
|
||||||
|
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||||
|
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||||
|
_configuration = kwargs.pop('_configuration', None)
|
||||||
|
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
|
||||||
|
|
||||||
|
self = super(OpenApiModel, cls).__new__(cls)
|
||||||
|
|
||||||
|
if args:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
|
||||||
|
args,
|
||||||
|
self.__class__.__name__,
|
||||||
|
),
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
self._data_store = {}
|
||||||
|
self._check_type = _check_type
|
||||||
|
self._spec_property_naming = _spec_property_naming
|
||||||
|
self._path_to_item = _path_to_item
|
||||||
|
self._configuration = _configuration
|
||||||
|
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||||
|
|
||||||
|
constant_args = {
|
||||||
|
'_check_type': _check_type,
|
||||||
|
'_path_to_item': _path_to_item,
|
||||||
|
'_spec_property_naming': _spec_property_naming,
|
||||||
|
'_configuration': _configuration,
|
||||||
|
'_visited_composed_classes': self._visited_composed_classes,
|
||||||
|
}
|
||||||
|
composed_info = validate_get_composed_info(
|
||||||
|
constant_args, kwargs, self)
|
||||||
|
self._composed_instances = composed_info[0]
|
||||||
|
self._var_name_to_model_instances = composed_info[1]
|
||||||
|
self._additional_properties_model_instances = composed_info[2]
|
||||||
|
discarded_args = composed_info[3]
|
||||||
|
|
||||||
|
for var_name, var_value in kwargs.items():
|
||||||
|
if var_name in discarded_args and \
|
||||||
|
self._configuration is not None and \
|
||||||
|
self._configuration.discard_unknown_keys and \
|
||||||
|
self._additional_properties_model_instances:
|
||||||
|
# discard variable.
|
||||||
|
continue
|
||||||
|
setattr(self, var_name, var_value)
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
required_properties = set([
|
||||||
|
'_data_store',
|
||||||
|
'_check_type',
|
||||||
|
'_spec_property_naming',
|
||||||
|
'_path_to_item',
|
||||||
|
'_configuration',
|
||||||
|
'_visited_composed_classes',
|
||||||
|
'_composed_instances',
|
||||||
|
'_var_name_to_model_instances',
|
||||||
|
'_additional_properties_model_instances',
|
||||||
|
])
|
||||||
|
|
||||||
|
@convert_js_args_to_python_args
|
||||||
|
def __init__(self, *args, **kwargs): # noqa: E501
|
||||||
|
"""ShamanFileSpecWithStatus - a model defined in OpenAPI
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
sha (str): SHA256 checksum of the file
|
||||||
|
size (int): File size in bytes
|
||||||
|
path (str): Location of the file in the checkout
|
||||||
|
status (ShamanFileStatus):
|
||||||
|
_check_type (bool): if True, values for parameters in openapi_types
|
||||||
|
will be type checked and a TypeError will be
|
||||||
|
raised if the wrong type is input.
|
||||||
|
Defaults to True
|
||||||
|
_path_to_item (tuple/list): This is a list of keys or values to
|
||||||
|
drill down to the model in received_data
|
||||||
|
when deserializing a response
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_configuration (Configuration): the instance to use when
|
||||||
|
deserializing a file_type parameter.
|
||||||
|
If passed, type conversion is attempted
|
||||||
|
If omitted no type conversion is done.
|
||||||
|
_visited_composed_classes (tuple): This stores a tuple of
|
||||||
|
classes that we have traveled through so that
|
||||||
|
if we see that class again we will not use its
|
||||||
|
discriminator again.
|
||||||
|
When traveling through a discriminator, the
|
||||||
|
composed schema that is
|
||||||
|
is traveled through is added to this set.
|
||||||
|
For example if Animal has a discriminator
|
||||||
|
petType and we pass in "Dog", and the class Dog
|
||||||
|
allOf includes Animal, we move through Animal
|
||||||
|
once using the discriminator, and pick Dog.
|
||||||
|
Then in Dog, we will make an instance of the
|
||||||
|
Animal class but this time we won't travel
|
||||||
|
through its discriminator because we passed in
|
||||||
|
_visited_composed_classes = (Animal,)
|
||||||
|
"""
|
||||||
|
|
||||||
|
_check_type = kwargs.pop('_check_type', True)
|
||||||
|
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||||
|
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||||
|
_configuration = kwargs.pop('_configuration', None)
|
||||||
|
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
|
||||||
|
|
||||||
|
if args:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
|
||||||
|
args,
|
||||||
|
self.__class__.__name__,
|
||||||
|
),
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
self._data_store = {}
|
||||||
|
self._check_type = _check_type
|
||||||
|
self._spec_property_naming = _spec_property_naming
|
||||||
|
self._path_to_item = _path_to_item
|
||||||
|
self._configuration = _configuration
|
||||||
|
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||||
|
|
||||||
|
constant_args = {
|
||||||
|
'_check_type': _check_type,
|
||||||
|
'_path_to_item': _path_to_item,
|
||||||
|
'_spec_property_naming': _spec_property_naming,
|
||||||
|
'_configuration': _configuration,
|
||||||
|
'_visited_composed_classes': self._visited_composed_classes,
|
||||||
|
}
|
||||||
|
composed_info = validate_get_composed_info(
|
||||||
|
constant_args, kwargs, self)
|
||||||
|
self._composed_instances = composed_info[0]
|
||||||
|
self._var_name_to_model_instances = composed_info[1]
|
||||||
|
self._additional_properties_model_instances = composed_info[2]
|
||||||
|
discarded_args = composed_info[3]
|
||||||
|
|
||||||
|
for var_name, var_value in kwargs.items():
|
||||||
|
if var_name in discarded_args and \
|
||||||
|
self._configuration is not None and \
|
||||||
|
self._configuration.discard_unknown_keys and \
|
||||||
|
self._additional_properties_model_instances:
|
||||||
|
# discard variable.
|
||||||
|
continue
|
||||||
|
setattr(self, var_name, var_value)
|
||||||
|
if var_name in self.read_only_vars:
|
||||||
|
raise ApiAttributeError(f"`{var_name}` is a read-only attribute. Use `from_openapi_data` to instantiate "
|
||||||
|
f"class with read only attributes.")
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def _composed_schemas():
|
||||||
|
# we need this here to make our import statements work
|
||||||
|
# we must store _composed_schemas in here so the code is only run
|
||||||
|
# when we invoke this method. If we kept this at the class
|
||||||
|
# level we would get an error because the class level
|
||||||
|
# code would be run when this module is imported, and these composed
|
||||||
|
# classes don't exist yet because their module has not finished
|
||||||
|
# loading
|
||||||
|
lazy_import()
|
||||||
|
return {
|
||||||
|
'anyOf': [
|
||||||
|
],
|
||||||
|
'allOf': [
|
||||||
|
ShamanFileSpec,
|
||||||
|
ShamanFileSpecWithStatusAllOf,
|
||||||
|
],
|
||||||
|
'oneOf': [
|
||||||
|
],
|
||||||
|
}
|
@ -0,0 +1,267 @@
|
|||||||
|
"""
|
||||||
|
Flamenco manager
|
||||||
|
|
||||||
|
Render Farm manager API # noqa: E501
|
||||||
|
|
||||||
|
The version of the OpenAPI document: 1.0.0
|
||||||
|
Generated by: https://openapi-generator.tech
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import re # noqa: F401
|
||||||
|
import sys # noqa: F401
|
||||||
|
|
||||||
|
from flamenco.manager.model_utils import ( # noqa: F401
|
||||||
|
ApiTypeError,
|
||||||
|
ModelComposed,
|
||||||
|
ModelNormal,
|
||||||
|
ModelSimple,
|
||||||
|
cached_property,
|
||||||
|
change_keys_js_to_python,
|
||||||
|
convert_js_args_to_python_args,
|
||||||
|
date,
|
||||||
|
datetime,
|
||||||
|
file_type,
|
||||||
|
none_type,
|
||||||
|
validate_get_composed_info,
|
||||||
|
OpenApiModel
|
||||||
|
)
|
||||||
|
from flamenco.manager.exceptions import ApiAttributeError
|
||||||
|
|
||||||
|
|
||||||
|
def lazy_import():
|
||||||
|
from flamenco.manager.model.shaman_file_status import ShamanFileStatus
|
||||||
|
globals()['ShamanFileStatus'] = ShamanFileStatus
|
||||||
|
|
||||||
|
|
||||||
|
class ShamanFileSpecWithStatusAllOf(ModelNormal):
|
||||||
|
"""NOTE: This class is auto generated by OpenAPI Generator.
|
||||||
|
Ref: https://openapi-generator.tech
|
||||||
|
|
||||||
|
Do not edit the class manually.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
allowed_values (dict): The key is the tuple path to the attribute
|
||||||
|
and the for var_name this is (var_name,). The value is a dict
|
||||||
|
with a capitalized key describing the allowed value and an allowed
|
||||||
|
value. These dicts store the allowed enum values.
|
||||||
|
attribute_map (dict): The key is attribute name
|
||||||
|
and the value is json key in definition.
|
||||||
|
discriminator_value_class_map (dict): A dict to go from the discriminator
|
||||||
|
variable value to the discriminator class name.
|
||||||
|
validations (dict): The key is the tuple path to the attribute
|
||||||
|
and the for var_name this is (var_name,). The value is a dict
|
||||||
|
that stores validations for max_length, min_length, max_items,
|
||||||
|
min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum,
|
||||||
|
inclusive_minimum, and regex.
|
||||||
|
additional_properties_type (tuple): A tuple of classes accepted
|
||||||
|
as additional properties values.
|
||||||
|
"""
|
||||||
|
|
||||||
|
allowed_values = {
|
||||||
|
}
|
||||||
|
|
||||||
|
validations = {
|
||||||
|
}
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def additional_properties_type():
|
||||||
|
"""
|
||||||
|
This must be a method because a model may have properties that are
|
||||||
|
of type self, this must run after the class is loaded
|
||||||
|
"""
|
||||||
|
lazy_import()
|
||||||
|
return (bool, date, datetime, dict, float, int, list, str, none_type,) # noqa: E501
|
||||||
|
|
||||||
|
_nullable = False
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def openapi_types():
|
||||||
|
"""
|
||||||
|
This must be a method because a model may have properties that are
|
||||||
|
of type self, this must run after the class is loaded
|
||||||
|
|
||||||
|
Returns
|
||||||
|
openapi_types (dict): The key is attribute name
|
||||||
|
and the value is attribute type.
|
||||||
|
"""
|
||||||
|
lazy_import()
|
||||||
|
return {
|
||||||
|
'status': (ShamanFileStatus,), # noqa: E501
|
||||||
|
}
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def discriminator():
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
attribute_map = {
|
||||||
|
'status': 'status', # noqa: E501
|
||||||
|
}
|
||||||
|
|
||||||
|
read_only_vars = {
|
||||||
|
}
|
||||||
|
|
||||||
|
_composed_schemas = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@convert_js_args_to_python_args
|
||||||
|
def _from_openapi_data(cls, status, *args, **kwargs): # noqa: E501
|
||||||
|
"""ShamanFileSpecWithStatusAllOf - a model defined in OpenAPI
|
||||||
|
|
||||||
|
Args:
|
||||||
|
status (ShamanFileStatus):
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
_check_type (bool): if True, values for parameters in openapi_types
|
||||||
|
will be type checked and a TypeError will be
|
||||||
|
raised if the wrong type is input.
|
||||||
|
Defaults to True
|
||||||
|
_path_to_item (tuple/list): This is a list of keys or values to
|
||||||
|
drill down to the model in received_data
|
||||||
|
when deserializing a response
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_configuration (Configuration): the instance to use when
|
||||||
|
deserializing a file_type parameter.
|
||||||
|
If passed, type conversion is attempted
|
||||||
|
If omitted no type conversion is done.
|
||||||
|
_visited_composed_classes (tuple): This stores a tuple of
|
||||||
|
classes that we have traveled through so that
|
||||||
|
if we see that class again we will not use its
|
||||||
|
discriminator again.
|
||||||
|
When traveling through a discriminator, the
|
||||||
|
composed schema that is
|
||||||
|
is traveled through is added to this set.
|
||||||
|
For example if Animal has a discriminator
|
||||||
|
petType and we pass in "Dog", and the class Dog
|
||||||
|
allOf includes Animal, we move through Animal
|
||||||
|
once using the discriminator, and pick Dog.
|
||||||
|
Then in Dog, we will make an instance of the
|
||||||
|
Animal class but this time we won't travel
|
||||||
|
through its discriminator because we passed in
|
||||||
|
_visited_composed_classes = (Animal,)
|
||||||
|
"""
|
||||||
|
|
||||||
|
_check_type = kwargs.pop('_check_type', True)
|
||||||
|
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||||
|
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||||
|
_configuration = kwargs.pop('_configuration', None)
|
||||||
|
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
|
||||||
|
|
||||||
|
self = super(OpenApiModel, cls).__new__(cls)
|
||||||
|
|
||||||
|
if args:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
|
||||||
|
args,
|
||||||
|
self.__class__.__name__,
|
||||||
|
),
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
self._data_store = {}
|
||||||
|
self._check_type = _check_type
|
||||||
|
self._spec_property_naming = _spec_property_naming
|
||||||
|
self._path_to_item = _path_to_item
|
||||||
|
self._configuration = _configuration
|
||||||
|
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||||
|
|
||||||
|
self.status = status
|
||||||
|
for var_name, var_value in kwargs.items():
|
||||||
|
if var_name not in self.attribute_map and \
|
||||||
|
self._configuration is not None and \
|
||||||
|
self._configuration.discard_unknown_keys and \
|
||||||
|
self.additional_properties_type is None:
|
||||||
|
# discard variable.
|
||||||
|
continue
|
||||||
|
setattr(self, var_name, var_value)
|
||||||
|
return self
|
||||||
|
|
||||||
|
required_properties = set([
|
||||||
|
'_data_store',
|
||||||
|
'_check_type',
|
||||||
|
'_spec_property_naming',
|
||||||
|
'_path_to_item',
|
||||||
|
'_configuration',
|
||||||
|
'_visited_composed_classes',
|
||||||
|
])
|
||||||
|
|
||||||
|
@convert_js_args_to_python_args
|
||||||
|
def __init__(self, status, *args, **kwargs): # noqa: E501
|
||||||
|
"""ShamanFileSpecWithStatusAllOf - a model defined in OpenAPI
|
||||||
|
|
||||||
|
Args:
|
||||||
|
status (ShamanFileStatus):
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
_check_type (bool): if True, values for parameters in openapi_types
|
||||||
|
will be type checked and a TypeError will be
|
||||||
|
raised if the wrong type is input.
|
||||||
|
Defaults to True
|
||||||
|
_path_to_item (tuple/list): This is a list of keys or values to
|
||||||
|
drill down to the model in received_data
|
||||||
|
when deserializing a response
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_configuration (Configuration): the instance to use when
|
||||||
|
deserializing a file_type parameter.
|
||||||
|
If passed, type conversion is attempted
|
||||||
|
If omitted no type conversion is done.
|
||||||
|
_visited_composed_classes (tuple): This stores a tuple of
|
||||||
|
classes that we have traveled through so that
|
||||||
|
if we see that class again we will not use its
|
||||||
|
discriminator again.
|
||||||
|
When traveling through a discriminator, the
|
||||||
|
composed schema that is
|
||||||
|
is traveled through is added to this set.
|
||||||
|
For example if Animal has a discriminator
|
||||||
|
petType and we pass in "Dog", and the class Dog
|
||||||
|
allOf includes Animal, we move through Animal
|
||||||
|
once using the discriminator, and pick Dog.
|
||||||
|
Then in Dog, we will make an instance of the
|
||||||
|
Animal class but this time we won't travel
|
||||||
|
through its discriminator because we passed in
|
||||||
|
_visited_composed_classes = (Animal,)
|
||||||
|
"""
|
||||||
|
|
||||||
|
_check_type = kwargs.pop('_check_type', True)
|
||||||
|
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||||
|
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||||
|
_configuration = kwargs.pop('_configuration', None)
|
||||||
|
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
|
||||||
|
|
||||||
|
if args:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
|
||||||
|
args,
|
||||||
|
self.__class__.__name__,
|
||||||
|
),
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
self._data_store = {}
|
||||||
|
self._check_type = _check_type
|
||||||
|
self._spec_property_naming = _spec_property_naming
|
||||||
|
self._path_to_item = _path_to_item
|
||||||
|
self._configuration = _configuration
|
||||||
|
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||||
|
|
||||||
|
self.status = status
|
||||||
|
for var_name, var_value in kwargs.items():
|
||||||
|
if var_name not in self.attribute_map and \
|
||||||
|
self._configuration is not None and \
|
||||||
|
self._configuration.discard_unknown_keys and \
|
||||||
|
self.additional_properties_type is None:
|
||||||
|
# discard variable.
|
||||||
|
continue
|
||||||
|
setattr(self, var_name, var_value)
|
||||||
|
if var_name in self.read_only_vars:
|
||||||
|
raise ApiAttributeError(f"`{var_name}` is a read-only attribute. Use `from_openapi_data` to instantiate "
|
||||||
|
f"class with read only attributes.")
|
283
addon/flamenco/manager/model/shaman_file_status.py
Normal file
283
addon/flamenco/manager/model/shaman_file_status.py
Normal file
@ -0,0 +1,283 @@
|
|||||||
|
"""
|
||||||
|
Flamenco manager
|
||||||
|
|
||||||
|
Render Farm manager API # noqa: E501
|
||||||
|
|
||||||
|
The version of the OpenAPI document: 1.0.0
|
||||||
|
Generated by: https://openapi-generator.tech
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import re # noqa: F401
|
||||||
|
import sys # noqa: F401
|
||||||
|
|
||||||
|
from flamenco.manager.model_utils import ( # noqa: F401
|
||||||
|
ApiTypeError,
|
||||||
|
ModelComposed,
|
||||||
|
ModelNormal,
|
||||||
|
ModelSimple,
|
||||||
|
cached_property,
|
||||||
|
change_keys_js_to_python,
|
||||||
|
convert_js_args_to_python_args,
|
||||||
|
date,
|
||||||
|
datetime,
|
||||||
|
file_type,
|
||||||
|
none_type,
|
||||||
|
validate_get_composed_info,
|
||||||
|
OpenApiModel
|
||||||
|
)
|
||||||
|
from flamenco.manager.exceptions import ApiAttributeError
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ShamanFileStatus(ModelSimple):
|
||||||
|
"""NOTE: This class is auto generated by OpenAPI Generator.
|
||||||
|
Ref: https://openapi-generator.tech
|
||||||
|
|
||||||
|
Do not edit the class manually.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
allowed_values (dict): The key is the tuple path to the attribute
|
||||||
|
and the for var_name this is (var_name,). The value is a dict
|
||||||
|
with a capitalized key describing the allowed value and an allowed
|
||||||
|
value. These dicts store the allowed enum values.
|
||||||
|
validations (dict): The key is the tuple path to the attribute
|
||||||
|
and the for var_name this is (var_name,). The value is a dict
|
||||||
|
that stores validations for max_length, min_length, max_items,
|
||||||
|
min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum,
|
||||||
|
inclusive_minimum, and regex.
|
||||||
|
additional_properties_type (tuple): A tuple of classes accepted
|
||||||
|
as additional properties values.
|
||||||
|
"""
|
||||||
|
|
||||||
|
allowed_values = {
|
||||||
|
('value',): {
|
||||||
|
'UNKNOWN': "unknown",
|
||||||
|
'UPLOADING': "uploading",
|
||||||
|
'STORED': "stored",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
validations = {
|
||||||
|
}
|
||||||
|
|
||||||
|
additional_properties_type = None
|
||||||
|
|
||||||
|
_nullable = False
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def openapi_types():
|
||||||
|
"""
|
||||||
|
This must be a method because a model may have properties that are
|
||||||
|
of type self, this must run after the class is loaded
|
||||||
|
|
||||||
|
Returns
|
||||||
|
openapi_types (dict): The key is attribute name
|
||||||
|
and the value is attribute type.
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
'value': (str,),
|
||||||
|
}
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def discriminator():
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
attribute_map = {}
|
||||||
|
|
||||||
|
read_only_vars = set()
|
||||||
|
|
||||||
|
_composed_schemas = None
|
||||||
|
|
||||||
|
required_properties = set([
|
||||||
|
'_data_store',
|
||||||
|
'_check_type',
|
||||||
|
'_spec_property_naming',
|
||||||
|
'_path_to_item',
|
||||||
|
'_configuration',
|
||||||
|
'_visited_composed_classes',
|
||||||
|
])
|
||||||
|
|
||||||
|
@convert_js_args_to_python_args
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
"""ShamanFileStatus - a model defined in OpenAPI
|
||||||
|
|
||||||
|
Note that value can be passed either in args or in kwargs, but not in both.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
args[0] (str):, must be one of ["unknown", "uploading", "stored", ] # noqa: E501
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
value (str):, must be one of ["unknown", "uploading", "stored", ] # noqa: E501
|
||||||
|
_check_type (bool): if True, values for parameters in openapi_types
|
||||||
|
will be type checked and a TypeError will be
|
||||||
|
raised if the wrong type is input.
|
||||||
|
Defaults to True
|
||||||
|
_path_to_item (tuple/list): This is a list of keys or values to
|
||||||
|
drill down to the model in received_data
|
||||||
|
when deserializing a response
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_configuration (Configuration): the instance to use when
|
||||||
|
deserializing a file_type parameter.
|
||||||
|
If passed, type conversion is attempted
|
||||||
|
If omitted no type conversion is done.
|
||||||
|
_visited_composed_classes (tuple): This stores a tuple of
|
||||||
|
classes that we have traveled through so that
|
||||||
|
if we see that class again we will not use its
|
||||||
|
discriminator again.
|
||||||
|
When traveling through a discriminator, the
|
||||||
|
composed schema that is
|
||||||
|
is traveled through is added to this set.
|
||||||
|
For example if Animal has a discriminator
|
||||||
|
petType and we pass in "Dog", and the class Dog
|
||||||
|
allOf includes Animal, we move through Animal
|
||||||
|
once using the discriminator, and pick Dog.
|
||||||
|
Then in Dog, we will make an instance of the
|
||||||
|
Animal class but this time we won't travel
|
||||||
|
through its discriminator because we passed in
|
||||||
|
_visited_composed_classes = (Animal,)
|
||||||
|
"""
|
||||||
|
# required up here when default value is not given
|
||||||
|
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||||
|
|
||||||
|
if 'value' in kwargs:
|
||||||
|
value = kwargs.pop('value')
|
||||||
|
elif args:
|
||||||
|
args = list(args)
|
||||||
|
value = args.pop(0)
|
||||||
|
else:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"value is required, but not passed in args or kwargs and doesn't have default",
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
_check_type = kwargs.pop('_check_type', True)
|
||||||
|
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||||
|
_configuration = kwargs.pop('_configuration', None)
|
||||||
|
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
|
||||||
|
|
||||||
|
if args:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
|
||||||
|
args,
|
||||||
|
self.__class__.__name__,
|
||||||
|
),
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
self._data_store = {}
|
||||||
|
self._check_type = _check_type
|
||||||
|
self._spec_property_naming = _spec_property_naming
|
||||||
|
self._path_to_item = _path_to_item
|
||||||
|
self._configuration = _configuration
|
||||||
|
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||||
|
self.value = value
|
||||||
|
if kwargs:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"Invalid named arguments=%s passed to %s. Remove those invalid named arguments." % (
|
||||||
|
kwargs,
|
||||||
|
self.__class__.__name__,
|
||||||
|
),
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@convert_js_args_to_python_args
|
||||||
|
def _from_openapi_data(cls, *args, **kwargs):
|
||||||
|
"""ShamanFileStatus - a model defined in OpenAPI
|
||||||
|
|
||||||
|
Note that value can be passed either in args or in kwargs, but not in both.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
args[0] (str):, must be one of ["unknown", "uploading", "stored", ] # noqa: E501
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
value (str):, must be one of ["unknown", "uploading", "stored", ] # noqa: E501
|
||||||
|
_check_type (bool): if True, values for parameters in openapi_types
|
||||||
|
will be type checked and a TypeError will be
|
||||||
|
raised if the wrong type is input.
|
||||||
|
Defaults to True
|
||||||
|
_path_to_item (tuple/list): This is a list of keys or values to
|
||||||
|
drill down to the model in received_data
|
||||||
|
when deserializing a response
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_configuration (Configuration): the instance to use when
|
||||||
|
deserializing a file_type parameter.
|
||||||
|
If passed, type conversion is attempted
|
||||||
|
If omitted no type conversion is done.
|
||||||
|
_visited_composed_classes (tuple): This stores a tuple of
|
||||||
|
classes that we have traveled through so that
|
||||||
|
if we see that class again we will not use its
|
||||||
|
discriminator again.
|
||||||
|
When traveling through a discriminator, the
|
||||||
|
composed schema that is
|
||||||
|
is traveled through is added to this set.
|
||||||
|
For example if Animal has a discriminator
|
||||||
|
petType and we pass in "Dog", and the class Dog
|
||||||
|
allOf includes Animal, we move through Animal
|
||||||
|
once using the discriminator, and pick Dog.
|
||||||
|
Then in Dog, we will make an instance of the
|
||||||
|
Animal class but this time we won't travel
|
||||||
|
through its discriminator because we passed in
|
||||||
|
_visited_composed_classes = (Animal,)
|
||||||
|
"""
|
||||||
|
# required up here when default value is not given
|
||||||
|
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||||
|
|
||||||
|
self = super(OpenApiModel, cls).__new__(cls)
|
||||||
|
|
||||||
|
if 'value' in kwargs:
|
||||||
|
value = kwargs.pop('value')
|
||||||
|
elif args:
|
||||||
|
args = list(args)
|
||||||
|
value = args.pop(0)
|
||||||
|
else:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"value is required, but not passed in args or kwargs and doesn't have default",
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
_check_type = kwargs.pop('_check_type', True)
|
||||||
|
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||||
|
_configuration = kwargs.pop('_configuration', None)
|
||||||
|
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
|
||||||
|
|
||||||
|
if args:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
|
||||||
|
args,
|
||||||
|
self.__class__.__name__,
|
||||||
|
),
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
self._data_store = {}
|
||||||
|
self._check_type = _check_type
|
||||||
|
self._spec_property_naming = _spec_property_naming
|
||||||
|
self._path_to_item = _path_to_item
|
||||||
|
self._configuration = _configuration
|
||||||
|
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||||
|
self.value = value
|
||||||
|
if kwargs:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"Invalid named arguments=%s passed to %s. Remove those invalid named arguments." % (
|
||||||
|
kwargs,
|
||||||
|
self.__class__.__name__,
|
||||||
|
),
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
return self
|
267
addon/flamenco/manager/model/shaman_requirements_request.py
Normal file
267
addon/flamenco/manager/model/shaman_requirements_request.py
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
"""
|
||||||
|
Flamenco manager
|
||||||
|
|
||||||
|
Render Farm manager API # noqa: E501
|
||||||
|
|
||||||
|
The version of the OpenAPI document: 1.0.0
|
||||||
|
Generated by: https://openapi-generator.tech
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import re # noqa: F401
|
||||||
|
import sys # noqa: F401
|
||||||
|
|
||||||
|
from flamenco.manager.model_utils import ( # noqa: F401
|
||||||
|
ApiTypeError,
|
||||||
|
ModelComposed,
|
||||||
|
ModelNormal,
|
||||||
|
ModelSimple,
|
||||||
|
cached_property,
|
||||||
|
change_keys_js_to_python,
|
||||||
|
convert_js_args_to_python_args,
|
||||||
|
date,
|
||||||
|
datetime,
|
||||||
|
file_type,
|
||||||
|
none_type,
|
||||||
|
validate_get_composed_info,
|
||||||
|
OpenApiModel
|
||||||
|
)
|
||||||
|
from flamenco.manager.exceptions import ApiAttributeError
|
||||||
|
|
||||||
|
|
||||||
|
def lazy_import():
|
||||||
|
from flamenco.manager.model.shaman_file_spec import ShamanFileSpec
|
||||||
|
globals()['ShamanFileSpec'] = ShamanFileSpec
|
||||||
|
|
||||||
|
|
||||||
|
class ShamanRequirementsRequest(ModelNormal):
|
||||||
|
"""NOTE: This class is auto generated by OpenAPI Generator.
|
||||||
|
Ref: https://openapi-generator.tech
|
||||||
|
|
||||||
|
Do not edit the class manually.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
allowed_values (dict): The key is the tuple path to the attribute
|
||||||
|
and the for var_name this is (var_name,). The value is a dict
|
||||||
|
with a capitalized key describing the allowed value and an allowed
|
||||||
|
value. These dicts store the allowed enum values.
|
||||||
|
attribute_map (dict): The key is attribute name
|
||||||
|
and the value is json key in definition.
|
||||||
|
discriminator_value_class_map (dict): A dict to go from the discriminator
|
||||||
|
variable value to the discriminator class name.
|
||||||
|
validations (dict): The key is the tuple path to the attribute
|
||||||
|
and the for var_name this is (var_name,). The value is a dict
|
||||||
|
that stores validations for max_length, min_length, max_items,
|
||||||
|
min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum,
|
||||||
|
inclusive_minimum, and regex.
|
||||||
|
additional_properties_type (tuple): A tuple of classes accepted
|
||||||
|
as additional properties values.
|
||||||
|
"""
|
||||||
|
|
||||||
|
allowed_values = {
|
||||||
|
}
|
||||||
|
|
||||||
|
validations = {
|
||||||
|
}
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def additional_properties_type():
|
||||||
|
"""
|
||||||
|
This must be a method because a model may have properties that are
|
||||||
|
of type self, this must run after the class is loaded
|
||||||
|
"""
|
||||||
|
lazy_import()
|
||||||
|
return (bool, date, datetime, dict, float, int, list, str, none_type,) # noqa: E501
|
||||||
|
|
||||||
|
_nullable = False
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def openapi_types():
|
||||||
|
"""
|
||||||
|
This must be a method because a model may have properties that are
|
||||||
|
of type self, this must run after the class is loaded
|
||||||
|
|
||||||
|
Returns
|
||||||
|
openapi_types (dict): The key is attribute name
|
||||||
|
and the value is attribute type.
|
||||||
|
"""
|
||||||
|
lazy_import()
|
||||||
|
return {
|
||||||
|
'files': ([ShamanFileSpec],), # noqa: E501
|
||||||
|
}
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def discriminator():
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
attribute_map = {
|
||||||
|
'files': 'files', # noqa: E501
|
||||||
|
}
|
||||||
|
|
||||||
|
read_only_vars = {
|
||||||
|
}
|
||||||
|
|
||||||
|
_composed_schemas = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@convert_js_args_to_python_args
|
||||||
|
def _from_openapi_data(cls, files, *args, **kwargs): # noqa: E501
|
||||||
|
"""ShamanRequirementsRequest - a model defined in OpenAPI
|
||||||
|
|
||||||
|
Args:
|
||||||
|
files ([ShamanFileSpec]):
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
_check_type (bool): if True, values for parameters in openapi_types
|
||||||
|
will be type checked and a TypeError will be
|
||||||
|
raised if the wrong type is input.
|
||||||
|
Defaults to True
|
||||||
|
_path_to_item (tuple/list): This is a list of keys or values to
|
||||||
|
drill down to the model in received_data
|
||||||
|
when deserializing a response
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_configuration (Configuration): the instance to use when
|
||||||
|
deserializing a file_type parameter.
|
||||||
|
If passed, type conversion is attempted
|
||||||
|
If omitted no type conversion is done.
|
||||||
|
_visited_composed_classes (tuple): This stores a tuple of
|
||||||
|
classes that we have traveled through so that
|
||||||
|
if we see that class again we will not use its
|
||||||
|
discriminator again.
|
||||||
|
When traveling through a discriminator, the
|
||||||
|
composed schema that is
|
||||||
|
is traveled through is added to this set.
|
||||||
|
For example if Animal has a discriminator
|
||||||
|
petType and we pass in "Dog", and the class Dog
|
||||||
|
allOf includes Animal, we move through Animal
|
||||||
|
once using the discriminator, and pick Dog.
|
||||||
|
Then in Dog, we will make an instance of the
|
||||||
|
Animal class but this time we won't travel
|
||||||
|
through its discriminator because we passed in
|
||||||
|
_visited_composed_classes = (Animal,)
|
||||||
|
"""
|
||||||
|
|
||||||
|
_check_type = kwargs.pop('_check_type', True)
|
||||||
|
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||||
|
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||||
|
_configuration = kwargs.pop('_configuration', None)
|
||||||
|
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
|
||||||
|
|
||||||
|
self = super(OpenApiModel, cls).__new__(cls)
|
||||||
|
|
||||||
|
if args:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
|
||||||
|
args,
|
||||||
|
self.__class__.__name__,
|
||||||
|
),
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
self._data_store = {}
|
||||||
|
self._check_type = _check_type
|
||||||
|
self._spec_property_naming = _spec_property_naming
|
||||||
|
self._path_to_item = _path_to_item
|
||||||
|
self._configuration = _configuration
|
||||||
|
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||||
|
|
||||||
|
self.files = files
|
||||||
|
for var_name, var_value in kwargs.items():
|
||||||
|
if var_name not in self.attribute_map and \
|
||||||
|
self._configuration is not None and \
|
||||||
|
self._configuration.discard_unknown_keys and \
|
||||||
|
self.additional_properties_type is None:
|
||||||
|
# discard variable.
|
||||||
|
continue
|
||||||
|
setattr(self, var_name, var_value)
|
||||||
|
return self
|
||||||
|
|
||||||
|
required_properties = set([
|
||||||
|
'_data_store',
|
||||||
|
'_check_type',
|
||||||
|
'_spec_property_naming',
|
||||||
|
'_path_to_item',
|
||||||
|
'_configuration',
|
||||||
|
'_visited_composed_classes',
|
||||||
|
])
|
||||||
|
|
||||||
|
@convert_js_args_to_python_args
|
||||||
|
def __init__(self, files, *args, **kwargs): # noqa: E501
|
||||||
|
"""ShamanRequirementsRequest - a model defined in OpenAPI
|
||||||
|
|
||||||
|
Args:
|
||||||
|
files ([ShamanFileSpec]):
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
_check_type (bool): if True, values for parameters in openapi_types
|
||||||
|
will be type checked and a TypeError will be
|
||||||
|
raised if the wrong type is input.
|
||||||
|
Defaults to True
|
||||||
|
_path_to_item (tuple/list): This is a list of keys or values to
|
||||||
|
drill down to the model in received_data
|
||||||
|
when deserializing a response
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_configuration (Configuration): the instance to use when
|
||||||
|
deserializing a file_type parameter.
|
||||||
|
If passed, type conversion is attempted
|
||||||
|
If omitted no type conversion is done.
|
||||||
|
_visited_composed_classes (tuple): This stores a tuple of
|
||||||
|
classes that we have traveled through so that
|
||||||
|
if we see that class again we will not use its
|
||||||
|
discriminator again.
|
||||||
|
When traveling through a discriminator, the
|
||||||
|
composed schema that is
|
||||||
|
is traveled through is added to this set.
|
||||||
|
For example if Animal has a discriminator
|
||||||
|
petType and we pass in "Dog", and the class Dog
|
||||||
|
allOf includes Animal, we move through Animal
|
||||||
|
once using the discriminator, and pick Dog.
|
||||||
|
Then in Dog, we will make an instance of the
|
||||||
|
Animal class but this time we won't travel
|
||||||
|
through its discriminator because we passed in
|
||||||
|
_visited_composed_classes = (Animal,)
|
||||||
|
"""
|
||||||
|
|
||||||
|
_check_type = kwargs.pop('_check_type', True)
|
||||||
|
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||||
|
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||||
|
_configuration = kwargs.pop('_configuration', None)
|
||||||
|
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
|
||||||
|
|
||||||
|
if args:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
|
||||||
|
args,
|
||||||
|
self.__class__.__name__,
|
||||||
|
),
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
self._data_store = {}
|
||||||
|
self._check_type = _check_type
|
||||||
|
self._spec_property_naming = _spec_property_naming
|
||||||
|
self._path_to_item = _path_to_item
|
||||||
|
self._configuration = _configuration
|
||||||
|
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||||
|
|
||||||
|
self.files = files
|
||||||
|
for var_name, var_value in kwargs.items():
|
||||||
|
if var_name not in self.attribute_map and \
|
||||||
|
self._configuration is not None and \
|
||||||
|
self._configuration.discard_unknown_keys and \
|
||||||
|
self.additional_properties_type is None:
|
||||||
|
# discard variable.
|
||||||
|
continue
|
||||||
|
setattr(self, var_name, var_value)
|
||||||
|
if var_name in self.read_only_vars:
|
||||||
|
raise ApiAttributeError(f"`{var_name}` is a read-only attribute. Use `from_openapi_data` to instantiate "
|
||||||
|
f"class with read only attributes.")
|
267
addon/flamenco/manager/model/shaman_requirements_response.py
Normal file
267
addon/flamenco/manager/model/shaman_requirements_response.py
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
"""
|
||||||
|
Flamenco manager
|
||||||
|
|
||||||
|
Render Farm manager API # noqa: E501
|
||||||
|
|
||||||
|
The version of the OpenAPI document: 1.0.0
|
||||||
|
Generated by: https://openapi-generator.tech
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import re # noqa: F401
|
||||||
|
import sys # noqa: F401
|
||||||
|
|
||||||
|
from flamenco.manager.model_utils import ( # noqa: F401
|
||||||
|
ApiTypeError,
|
||||||
|
ModelComposed,
|
||||||
|
ModelNormal,
|
||||||
|
ModelSimple,
|
||||||
|
cached_property,
|
||||||
|
change_keys_js_to_python,
|
||||||
|
convert_js_args_to_python_args,
|
||||||
|
date,
|
||||||
|
datetime,
|
||||||
|
file_type,
|
||||||
|
none_type,
|
||||||
|
validate_get_composed_info,
|
||||||
|
OpenApiModel
|
||||||
|
)
|
||||||
|
from flamenco.manager.exceptions import ApiAttributeError
|
||||||
|
|
||||||
|
|
||||||
|
def lazy_import():
|
||||||
|
from flamenco.manager.model.shaman_file_spec_with_status import ShamanFileSpecWithStatus
|
||||||
|
globals()['ShamanFileSpecWithStatus'] = ShamanFileSpecWithStatus
|
||||||
|
|
||||||
|
|
||||||
|
class ShamanRequirementsResponse(ModelNormal):
|
||||||
|
"""NOTE: This class is auto generated by OpenAPI Generator.
|
||||||
|
Ref: https://openapi-generator.tech
|
||||||
|
|
||||||
|
Do not edit the class manually.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
allowed_values (dict): The key is the tuple path to the attribute
|
||||||
|
and the for var_name this is (var_name,). The value is a dict
|
||||||
|
with a capitalized key describing the allowed value and an allowed
|
||||||
|
value. These dicts store the allowed enum values.
|
||||||
|
attribute_map (dict): The key is attribute name
|
||||||
|
and the value is json key in definition.
|
||||||
|
discriminator_value_class_map (dict): A dict to go from the discriminator
|
||||||
|
variable value to the discriminator class name.
|
||||||
|
validations (dict): The key is the tuple path to the attribute
|
||||||
|
and the for var_name this is (var_name,). The value is a dict
|
||||||
|
that stores validations for max_length, min_length, max_items,
|
||||||
|
min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum,
|
||||||
|
inclusive_minimum, and regex.
|
||||||
|
additional_properties_type (tuple): A tuple of classes accepted
|
||||||
|
as additional properties values.
|
||||||
|
"""
|
||||||
|
|
||||||
|
allowed_values = {
|
||||||
|
}
|
||||||
|
|
||||||
|
validations = {
|
||||||
|
}
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def additional_properties_type():
|
||||||
|
"""
|
||||||
|
This must be a method because a model may have properties that are
|
||||||
|
of type self, this must run after the class is loaded
|
||||||
|
"""
|
||||||
|
lazy_import()
|
||||||
|
return (bool, date, datetime, dict, float, int, list, str, none_type,) # noqa: E501
|
||||||
|
|
||||||
|
_nullable = False
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def openapi_types():
|
||||||
|
"""
|
||||||
|
This must be a method because a model may have properties that are
|
||||||
|
of type self, this must run after the class is loaded
|
||||||
|
|
||||||
|
Returns
|
||||||
|
openapi_types (dict): The key is attribute name
|
||||||
|
and the value is attribute type.
|
||||||
|
"""
|
||||||
|
lazy_import()
|
||||||
|
return {
|
||||||
|
'files': ([ShamanFileSpecWithStatus],), # noqa: E501
|
||||||
|
}
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def discriminator():
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
attribute_map = {
|
||||||
|
'files': 'files', # noqa: E501
|
||||||
|
}
|
||||||
|
|
||||||
|
read_only_vars = {
|
||||||
|
}
|
||||||
|
|
||||||
|
_composed_schemas = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@convert_js_args_to_python_args
|
||||||
|
def _from_openapi_data(cls, files, *args, **kwargs): # noqa: E501
|
||||||
|
"""ShamanRequirementsResponse - a model defined in OpenAPI
|
||||||
|
|
||||||
|
Args:
|
||||||
|
files ([ShamanFileSpecWithStatus]):
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
_check_type (bool): if True, values for parameters in openapi_types
|
||||||
|
will be type checked and a TypeError will be
|
||||||
|
raised if the wrong type is input.
|
||||||
|
Defaults to True
|
||||||
|
_path_to_item (tuple/list): This is a list of keys or values to
|
||||||
|
drill down to the model in received_data
|
||||||
|
when deserializing a response
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_configuration (Configuration): the instance to use when
|
||||||
|
deserializing a file_type parameter.
|
||||||
|
If passed, type conversion is attempted
|
||||||
|
If omitted no type conversion is done.
|
||||||
|
_visited_composed_classes (tuple): This stores a tuple of
|
||||||
|
classes that we have traveled through so that
|
||||||
|
if we see that class again we will not use its
|
||||||
|
discriminator again.
|
||||||
|
When traveling through a discriminator, the
|
||||||
|
composed schema that is
|
||||||
|
is traveled through is added to this set.
|
||||||
|
For example if Animal has a discriminator
|
||||||
|
petType and we pass in "Dog", and the class Dog
|
||||||
|
allOf includes Animal, we move through Animal
|
||||||
|
once using the discriminator, and pick Dog.
|
||||||
|
Then in Dog, we will make an instance of the
|
||||||
|
Animal class but this time we won't travel
|
||||||
|
through its discriminator because we passed in
|
||||||
|
_visited_composed_classes = (Animal,)
|
||||||
|
"""
|
||||||
|
|
||||||
|
_check_type = kwargs.pop('_check_type', True)
|
||||||
|
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||||
|
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||||
|
_configuration = kwargs.pop('_configuration', None)
|
||||||
|
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
|
||||||
|
|
||||||
|
self = super(OpenApiModel, cls).__new__(cls)
|
||||||
|
|
||||||
|
if args:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
|
||||||
|
args,
|
||||||
|
self.__class__.__name__,
|
||||||
|
),
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
self._data_store = {}
|
||||||
|
self._check_type = _check_type
|
||||||
|
self._spec_property_naming = _spec_property_naming
|
||||||
|
self._path_to_item = _path_to_item
|
||||||
|
self._configuration = _configuration
|
||||||
|
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||||
|
|
||||||
|
self.files = files
|
||||||
|
for var_name, var_value in kwargs.items():
|
||||||
|
if var_name not in self.attribute_map and \
|
||||||
|
self._configuration is not None and \
|
||||||
|
self._configuration.discard_unknown_keys and \
|
||||||
|
self.additional_properties_type is None:
|
||||||
|
# discard variable.
|
||||||
|
continue
|
||||||
|
setattr(self, var_name, var_value)
|
||||||
|
return self
|
||||||
|
|
||||||
|
required_properties = set([
|
||||||
|
'_data_store',
|
||||||
|
'_check_type',
|
||||||
|
'_spec_property_naming',
|
||||||
|
'_path_to_item',
|
||||||
|
'_configuration',
|
||||||
|
'_visited_composed_classes',
|
||||||
|
])
|
||||||
|
|
||||||
|
@convert_js_args_to_python_args
|
||||||
|
def __init__(self, files, *args, **kwargs): # noqa: E501
|
||||||
|
"""ShamanRequirementsResponse - a model defined in OpenAPI
|
||||||
|
|
||||||
|
Args:
|
||||||
|
files ([ShamanFileSpecWithStatus]):
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
_check_type (bool): if True, values for parameters in openapi_types
|
||||||
|
will be type checked and a TypeError will be
|
||||||
|
raised if the wrong type is input.
|
||||||
|
Defaults to True
|
||||||
|
_path_to_item (tuple/list): This is a list of keys or values to
|
||||||
|
drill down to the model in received_data
|
||||||
|
when deserializing a response
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_configuration (Configuration): the instance to use when
|
||||||
|
deserializing a file_type parameter.
|
||||||
|
If passed, type conversion is attempted
|
||||||
|
If omitted no type conversion is done.
|
||||||
|
_visited_composed_classes (tuple): This stores a tuple of
|
||||||
|
classes that we have traveled through so that
|
||||||
|
if we see that class again we will not use its
|
||||||
|
discriminator again.
|
||||||
|
When traveling through a discriminator, the
|
||||||
|
composed schema that is
|
||||||
|
is traveled through is added to this set.
|
||||||
|
For example if Animal has a discriminator
|
||||||
|
petType and we pass in "Dog", and the class Dog
|
||||||
|
allOf includes Animal, we move through Animal
|
||||||
|
once using the discriminator, and pick Dog.
|
||||||
|
Then in Dog, we will make an instance of the
|
||||||
|
Animal class but this time we won't travel
|
||||||
|
through its discriminator because we passed in
|
||||||
|
_visited_composed_classes = (Animal,)
|
||||||
|
"""
|
||||||
|
|
||||||
|
_check_type = kwargs.pop('_check_type', True)
|
||||||
|
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||||
|
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||||
|
_configuration = kwargs.pop('_configuration', None)
|
||||||
|
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
|
||||||
|
|
||||||
|
if args:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
|
||||||
|
args,
|
||||||
|
self.__class__.__name__,
|
||||||
|
),
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
self._data_store = {}
|
||||||
|
self._check_type = _check_type
|
||||||
|
self._spec_property_naming = _spec_property_naming
|
||||||
|
self._path_to_item = _path_to_item
|
||||||
|
self._configuration = _configuration
|
||||||
|
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||||
|
|
||||||
|
self.files = files
|
||||||
|
for var_name, var_value in kwargs.items():
|
||||||
|
if var_name not in self.attribute_map and \
|
||||||
|
self._configuration is not None and \
|
||||||
|
self._configuration.discard_unknown_keys and \
|
||||||
|
self.additional_properties_type is None:
|
||||||
|
# discard variable.
|
||||||
|
continue
|
||||||
|
setattr(self, var_name, var_value)
|
||||||
|
if var_name in self.read_only_vars:
|
||||||
|
raise ApiAttributeError(f"`{var_name}` is a read-only attribute. Use `from_openapi_data` to instantiate "
|
||||||
|
f"class with read only attributes.")
|
267
addon/flamenco/manager/model/shaman_single_file_status.py
Normal file
267
addon/flamenco/manager/model/shaman_single_file_status.py
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
"""
|
||||||
|
Flamenco manager
|
||||||
|
|
||||||
|
Render Farm manager API # noqa: E501
|
||||||
|
|
||||||
|
The version of the OpenAPI document: 1.0.0
|
||||||
|
Generated by: https://openapi-generator.tech
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import re # noqa: F401
|
||||||
|
import sys # noqa: F401
|
||||||
|
|
||||||
|
from flamenco.manager.model_utils import ( # noqa: F401
|
||||||
|
ApiTypeError,
|
||||||
|
ModelComposed,
|
||||||
|
ModelNormal,
|
||||||
|
ModelSimple,
|
||||||
|
cached_property,
|
||||||
|
change_keys_js_to_python,
|
||||||
|
convert_js_args_to_python_args,
|
||||||
|
date,
|
||||||
|
datetime,
|
||||||
|
file_type,
|
||||||
|
none_type,
|
||||||
|
validate_get_composed_info,
|
||||||
|
OpenApiModel
|
||||||
|
)
|
||||||
|
from flamenco.manager.exceptions import ApiAttributeError
|
||||||
|
|
||||||
|
|
||||||
|
def lazy_import():
|
||||||
|
from flamenco.manager.model.shaman_file_status import ShamanFileStatus
|
||||||
|
globals()['ShamanFileStatus'] = ShamanFileStatus
|
||||||
|
|
||||||
|
|
||||||
|
class ShamanSingleFileStatus(ModelNormal):
|
||||||
|
"""NOTE: This class is auto generated by OpenAPI Generator.
|
||||||
|
Ref: https://openapi-generator.tech
|
||||||
|
|
||||||
|
Do not edit the class manually.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
allowed_values (dict): The key is the tuple path to the attribute
|
||||||
|
and the for var_name this is (var_name,). The value is a dict
|
||||||
|
with a capitalized key describing the allowed value and an allowed
|
||||||
|
value. These dicts store the allowed enum values.
|
||||||
|
attribute_map (dict): The key is attribute name
|
||||||
|
and the value is json key in definition.
|
||||||
|
discriminator_value_class_map (dict): A dict to go from the discriminator
|
||||||
|
variable value to the discriminator class name.
|
||||||
|
validations (dict): The key is the tuple path to the attribute
|
||||||
|
and the for var_name this is (var_name,). The value is a dict
|
||||||
|
that stores validations for max_length, min_length, max_items,
|
||||||
|
min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum,
|
||||||
|
inclusive_minimum, and regex.
|
||||||
|
additional_properties_type (tuple): A tuple of classes accepted
|
||||||
|
as additional properties values.
|
||||||
|
"""
|
||||||
|
|
||||||
|
allowed_values = {
|
||||||
|
}
|
||||||
|
|
||||||
|
validations = {
|
||||||
|
}
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def additional_properties_type():
|
||||||
|
"""
|
||||||
|
This must be a method because a model may have properties that are
|
||||||
|
of type self, this must run after the class is loaded
|
||||||
|
"""
|
||||||
|
lazy_import()
|
||||||
|
return (bool, date, datetime, dict, float, int, list, str, none_type,) # noqa: E501
|
||||||
|
|
||||||
|
_nullable = False
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def openapi_types():
|
||||||
|
"""
|
||||||
|
This must be a method because a model may have properties that are
|
||||||
|
of type self, this must run after the class is loaded
|
||||||
|
|
||||||
|
Returns
|
||||||
|
openapi_types (dict): The key is attribute name
|
||||||
|
and the value is attribute type.
|
||||||
|
"""
|
||||||
|
lazy_import()
|
||||||
|
return {
|
||||||
|
'status': (ShamanFileStatus,), # noqa: E501
|
||||||
|
}
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def discriminator():
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
attribute_map = {
|
||||||
|
'status': 'status', # noqa: E501
|
||||||
|
}
|
||||||
|
|
||||||
|
read_only_vars = {
|
||||||
|
}
|
||||||
|
|
||||||
|
_composed_schemas = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@convert_js_args_to_python_args
|
||||||
|
def _from_openapi_data(cls, status, *args, **kwargs): # noqa: E501
|
||||||
|
"""ShamanSingleFileStatus - a model defined in OpenAPI
|
||||||
|
|
||||||
|
Args:
|
||||||
|
status (ShamanFileStatus):
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
_check_type (bool): if True, values for parameters in openapi_types
|
||||||
|
will be type checked and a TypeError will be
|
||||||
|
raised if the wrong type is input.
|
||||||
|
Defaults to True
|
||||||
|
_path_to_item (tuple/list): This is a list of keys or values to
|
||||||
|
drill down to the model in received_data
|
||||||
|
when deserializing a response
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_configuration (Configuration): the instance to use when
|
||||||
|
deserializing a file_type parameter.
|
||||||
|
If passed, type conversion is attempted
|
||||||
|
If omitted no type conversion is done.
|
||||||
|
_visited_composed_classes (tuple): This stores a tuple of
|
||||||
|
classes that we have traveled through so that
|
||||||
|
if we see that class again we will not use its
|
||||||
|
discriminator again.
|
||||||
|
When traveling through a discriminator, the
|
||||||
|
composed schema that is
|
||||||
|
is traveled through is added to this set.
|
||||||
|
For example if Animal has a discriminator
|
||||||
|
petType and we pass in "Dog", and the class Dog
|
||||||
|
allOf includes Animal, we move through Animal
|
||||||
|
once using the discriminator, and pick Dog.
|
||||||
|
Then in Dog, we will make an instance of the
|
||||||
|
Animal class but this time we won't travel
|
||||||
|
through its discriminator because we passed in
|
||||||
|
_visited_composed_classes = (Animal,)
|
||||||
|
"""
|
||||||
|
|
||||||
|
_check_type = kwargs.pop('_check_type', True)
|
||||||
|
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||||
|
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||||
|
_configuration = kwargs.pop('_configuration', None)
|
||||||
|
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
|
||||||
|
|
||||||
|
self = super(OpenApiModel, cls).__new__(cls)
|
||||||
|
|
||||||
|
if args:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
|
||||||
|
args,
|
||||||
|
self.__class__.__name__,
|
||||||
|
),
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
self._data_store = {}
|
||||||
|
self._check_type = _check_type
|
||||||
|
self._spec_property_naming = _spec_property_naming
|
||||||
|
self._path_to_item = _path_to_item
|
||||||
|
self._configuration = _configuration
|
||||||
|
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||||
|
|
||||||
|
self.status = status
|
||||||
|
for var_name, var_value in kwargs.items():
|
||||||
|
if var_name not in self.attribute_map and \
|
||||||
|
self._configuration is not None and \
|
||||||
|
self._configuration.discard_unknown_keys and \
|
||||||
|
self.additional_properties_type is None:
|
||||||
|
# discard variable.
|
||||||
|
continue
|
||||||
|
setattr(self, var_name, var_value)
|
||||||
|
return self
|
||||||
|
|
||||||
|
required_properties = set([
|
||||||
|
'_data_store',
|
||||||
|
'_check_type',
|
||||||
|
'_spec_property_naming',
|
||||||
|
'_path_to_item',
|
||||||
|
'_configuration',
|
||||||
|
'_visited_composed_classes',
|
||||||
|
])
|
||||||
|
|
||||||
|
@convert_js_args_to_python_args
|
||||||
|
def __init__(self, status, *args, **kwargs): # noqa: E501
|
||||||
|
"""ShamanSingleFileStatus - a model defined in OpenAPI
|
||||||
|
|
||||||
|
Args:
|
||||||
|
status (ShamanFileStatus):
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
_check_type (bool): if True, values for parameters in openapi_types
|
||||||
|
will be type checked and a TypeError will be
|
||||||
|
raised if the wrong type is input.
|
||||||
|
Defaults to True
|
||||||
|
_path_to_item (tuple/list): This is a list of keys or values to
|
||||||
|
drill down to the model in received_data
|
||||||
|
when deserializing a response
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_configuration (Configuration): the instance to use when
|
||||||
|
deserializing a file_type parameter.
|
||||||
|
If passed, type conversion is attempted
|
||||||
|
If omitted no type conversion is done.
|
||||||
|
_visited_composed_classes (tuple): This stores a tuple of
|
||||||
|
classes that we have traveled through so that
|
||||||
|
if we see that class again we will not use its
|
||||||
|
discriminator again.
|
||||||
|
When traveling through a discriminator, the
|
||||||
|
composed schema that is
|
||||||
|
is traveled through is added to this set.
|
||||||
|
For example if Animal has a discriminator
|
||||||
|
petType and we pass in "Dog", and the class Dog
|
||||||
|
allOf includes Animal, we move through Animal
|
||||||
|
once using the discriminator, and pick Dog.
|
||||||
|
Then in Dog, we will make an instance of the
|
||||||
|
Animal class but this time we won't travel
|
||||||
|
through its discriminator because we passed in
|
||||||
|
_visited_composed_classes = (Animal,)
|
||||||
|
"""
|
||||||
|
|
||||||
|
_check_type = kwargs.pop('_check_type', True)
|
||||||
|
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||||
|
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||||
|
_configuration = kwargs.pop('_configuration', None)
|
||||||
|
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
|
||||||
|
|
||||||
|
if args:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
|
||||||
|
args,
|
||||||
|
self.__class__.__name__,
|
||||||
|
),
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
self._data_store = {}
|
||||||
|
self._check_type = _check_type
|
||||||
|
self._spec_property_naming = _spec_property_naming
|
||||||
|
self._path_to_item = _path_to_item
|
||||||
|
self._configuration = _configuration
|
||||||
|
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||||
|
|
||||||
|
self.status = status
|
||||||
|
for var_name, var_value in kwargs.items():
|
||||||
|
if var_name not in self.attribute_map and \
|
||||||
|
self._configuration is not None and \
|
||||||
|
self._configuration.discard_unknown_keys and \
|
||||||
|
self.additional_properties_type is None:
|
||||||
|
# discard variable.
|
||||||
|
continue
|
||||||
|
setattr(self, var_name, var_value)
|
||||||
|
if var_name in self.read_only_vars:
|
||||||
|
raise ApiAttributeError(f"`{var_name}` is a read-only attribute. Use `from_openapi_data` to instantiate "
|
||||||
|
f"class with read only attributes.")
|
@ -25,6 +25,14 @@ from flamenco.manager.model.job_settings import JobSettings
|
|||||||
from flamenco.manager.model.job_status import JobStatus
|
from flamenco.manager.model.job_status import JobStatus
|
||||||
from flamenco.manager.model.registered_worker import RegisteredWorker
|
from flamenco.manager.model.registered_worker import RegisteredWorker
|
||||||
from flamenco.manager.model.security_error import SecurityError
|
from flamenco.manager.model.security_error import SecurityError
|
||||||
|
from flamenco.manager.model.shaman_checkout import ShamanCheckout
|
||||||
|
from flamenco.manager.model.shaman_file_spec import ShamanFileSpec
|
||||||
|
from flamenco.manager.model.shaman_file_spec_with_status import ShamanFileSpecWithStatus
|
||||||
|
from flamenco.manager.model.shaman_file_spec_with_status_all_of import ShamanFileSpecWithStatusAllOf
|
||||||
|
from flamenco.manager.model.shaman_file_status import ShamanFileStatus
|
||||||
|
from flamenco.manager.model.shaman_requirements_request import ShamanRequirementsRequest
|
||||||
|
from flamenco.manager.model.shaman_requirements_response import ShamanRequirementsResponse
|
||||||
|
from flamenco.manager.model.shaman_single_file_status import ShamanSingleFileStatus
|
||||||
from flamenco.manager.model.submitted_job import SubmittedJob
|
from flamenco.manager.model.submitted_job import SubmittedJob
|
||||||
from flamenco.manager.model.task_status import TaskStatus
|
from flamenco.manager.model.task_status import TaskStatus
|
||||||
from flamenco.manager.model.task_update import TaskUpdate
|
from flamenco.manager.model.task_update import TaskUpdate
|
||||||
|
@ -4,7 +4,7 @@ Render Farm manager API
|
|||||||
The `flamenco.manager` package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
The `flamenco.manager` package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||||
|
|
||||||
- API version: 1.0.0
|
- API version: 1.0.0
|
||||||
- Package version: 7bfde1df-dirty
|
- Package version: 63793f42-dirty
|
||||||
- Build package: org.openapitools.codegen.languages.PythonClientCodegen
|
- Build package: org.openapitools.codegen.languages.PythonClientCodegen
|
||||||
For more information, please visit [https://flamenco.io/](https://flamenco.io/)
|
For more information, please visit [https://flamenco.io/](https://flamenco.io/)
|
||||||
|
|
||||||
@ -68,6 +68,10 @@ Class | Method | HTTP request | Description
|
|||||||
*JobsApi* | [**get_job_types**](flamenco/manager/docs/JobsApi.md#get_job_types) | **GET** /api/jobs/types | Get list of job types and their parameters.
|
*JobsApi* | [**get_job_types**](flamenco/manager/docs/JobsApi.md#get_job_types) | **GET** /api/jobs/types | Get list of job types and their parameters.
|
||||||
*JobsApi* | [**submit_job**](flamenco/manager/docs/JobsApi.md#submit_job) | **POST** /api/jobs | Submit a new job for Flamenco Manager to execute.
|
*JobsApi* | [**submit_job**](flamenco/manager/docs/JobsApi.md#submit_job) | **POST** /api/jobs | Submit a new job for Flamenco Manager to execute.
|
||||||
*MetaApi* | [**get_version**](flamenco/manager/docs/MetaApi.md#get_version) | **GET** /api/version | Get the Flamenco version of this Manager
|
*MetaApi* | [**get_version**](flamenco/manager/docs/MetaApi.md#get_version) | **GET** /api/version | Get the Flamenco version of this Manager
|
||||||
|
*ShamanApi* | [**shaman_checkout**](flamenco/manager/docs/ShamanApi.md#shaman_checkout) | **POST** /shaman/checkout/create | Create a directory, and symlink the required files into it. The files must all have been uploaded to Shaman before calling this endpoint.
|
||||||
|
*ShamanApi* | [**shaman_checkout_requirements**](flamenco/manager/docs/ShamanApi.md#shaman_checkout_requirements) | **POST** /shaman/checkout/requirements | Checks a Shaman Requirements file, and reports which files are unknown.
|
||||||
|
*ShamanApi* | [**shaman_file_store**](flamenco/manager/docs/ShamanApi.md#shaman_file_store) | **POST** /shaman/files/{checksum}/{filesize} | Store a new file on the Shaman server. Note that the Shaman server can forcibly close the HTTP connection when another client finishes uploading the exact same file, to prevent double uploads. The file's contents should be sent in the request body.
|
||||||
|
*ShamanApi* | [**shaman_file_store_check**](flamenco/manager/docs/ShamanApi.md#shaman_file_store_check) | **OPTIONS** /shaman/files/{checksum}/{filesize} | Check the status of a file on the Shaman server.
|
||||||
*WorkerApi* | [**register_worker**](flamenco/manager/docs/WorkerApi.md#register_worker) | **POST** /api/worker/register-worker | Register a new worker
|
*WorkerApi* | [**register_worker**](flamenco/manager/docs/WorkerApi.md#register_worker) | **POST** /api/worker/register-worker | Register a new worker
|
||||||
*WorkerApi* | [**schedule_task**](flamenco/manager/docs/WorkerApi.md#schedule_task) | **POST** /api/worker/task | Obtain a new task to execute
|
*WorkerApi* | [**schedule_task**](flamenco/manager/docs/WorkerApi.md#schedule_task) | **POST** /api/worker/task | Obtain a new task to execute
|
||||||
*WorkerApi* | [**sign_off**](flamenco/manager/docs/WorkerApi.md#sign_off) | **POST** /api/worker/sign-off | Mark the worker as offline
|
*WorkerApi* | [**sign_off**](flamenco/manager/docs/WorkerApi.md#sign_off) | **POST** /api/worker/sign-off | Mark the worker as offline
|
||||||
@ -95,6 +99,14 @@ Class | Method | HTTP request | Description
|
|||||||
- [JobStatus](flamenco/manager/docs/JobStatus.md)
|
- [JobStatus](flamenco/manager/docs/JobStatus.md)
|
||||||
- [RegisteredWorker](flamenco/manager/docs/RegisteredWorker.md)
|
- [RegisteredWorker](flamenco/manager/docs/RegisteredWorker.md)
|
||||||
- [SecurityError](flamenco/manager/docs/SecurityError.md)
|
- [SecurityError](flamenco/manager/docs/SecurityError.md)
|
||||||
|
- [ShamanCheckout](flamenco/manager/docs/ShamanCheckout.md)
|
||||||
|
- [ShamanFileSpec](flamenco/manager/docs/ShamanFileSpec.md)
|
||||||
|
- [ShamanFileSpecWithStatus](flamenco/manager/docs/ShamanFileSpecWithStatus.md)
|
||||||
|
- [ShamanFileSpecWithStatusAllOf](flamenco/manager/docs/ShamanFileSpecWithStatusAllOf.md)
|
||||||
|
- [ShamanFileStatus](flamenco/manager/docs/ShamanFileStatus.md)
|
||||||
|
- [ShamanRequirementsRequest](flamenco/manager/docs/ShamanRequirementsRequest.md)
|
||||||
|
- [ShamanRequirementsResponse](flamenco/manager/docs/ShamanRequirementsResponse.md)
|
||||||
|
- [ShamanSingleFileStatus](flamenco/manager/docs/ShamanSingleFileStatus.md)
|
||||||
- [SubmittedJob](flamenco/manager/docs/SubmittedJob.md)
|
- [SubmittedJob](flamenco/manager/docs/SubmittedJob.md)
|
||||||
- [TaskStatus](flamenco/manager/docs/TaskStatus.md)
|
- [TaskStatus](flamenco/manager/docs/TaskStatus.md)
|
||||||
- [TaskUpdate](flamenco/manager/docs/TaskUpdate.md)
|
- [TaskUpdate](flamenco/manager/docs/TaskUpdate.md)
|
||||||
|
@ -315,7 +315,7 @@ class FLAMENCO3_OT_explore_file_path(bpy.types.Operator):
|
|||||||
bl_label = "Open in file explorer"
|
bl_label = "Open in file explorer"
|
||||||
bl_description = __doc__.rstrip(".")
|
bl_description = __doc__.rstrip(".")
|
||||||
|
|
||||||
path: bpy.props.StringProperty(
|
path: bpy.props.StringProperty( # type: ignore
|
||||||
name="Path", description="Path to explore", subtype="DIR_PATH"
|
name="Path", description="Path to explore", subtype="DIR_PATH"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -334,22 +334,22 @@ class FLAMENCO3_OT_explore_file_path(bpy.types.Operator):
|
|||||||
{"ERROR"}, "Unable to open %s or any of its parents." % self.path
|
{"ERROR"}, "Unable to open %s or any of its parents." % self.path
|
||||||
)
|
)
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
to_open = str(to_open)
|
|
||||||
|
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
import os
|
import os
|
||||||
|
|
||||||
os.startfile(to_open)
|
# Ignore the mypy error here, as os.startfile() only exists on Windows.
|
||||||
|
os.startfile(str(to_open)) # type: ignore
|
||||||
|
|
||||||
elif platform.system() == "Darwin":
|
elif platform.system() == "Darwin":
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
subprocess.Popen(["open", to_open])
|
subprocess.Popen(["open", str(to_open)])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
subprocess.Popen(["xdg-open", to_open])
|
subprocess.Popen(["xdg-open", str(to_open)])
|
||||||
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
@ -80,17 +80,9 @@ func (f *Flamenco) ShamanFileStoreCheck(e echo.Context, checksum string, filesiz
|
|||||||
logger.Debug().Msg("shaman: checking file")
|
logger.Debug().Msg("shaman: checking file")
|
||||||
status := f.shaman.FileStoreCheck(e.Request().Context(), checksum, int64(filesize))
|
status := f.shaman.FileStoreCheck(e.Request().Context(), checksum, int64(filesize))
|
||||||
|
|
||||||
// TODO: actually switch over the actual statuses, see the TODO in the Shaman interface.
|
return e.JSON(http.StatusOK, api.ShamanSingleFileStatus{
|
||||||
switch status {
|
Status: status,
|
||||||
case api.ShamanFileStatusStored:
|
})
|
||||||
return e.String(http.StatusOK, "")
|
|
||||||
case api.ShamanFileStatusUploading:
|
|
||||||
return e.String(420 /* Enhance Your Calm */, "")
|
|
||||||
case api.ShamanFileStatusUnknown:
|
|
||||||
return e.String(http.StatusNotFound, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
return sendAPIError(e, http.StatusInternalServerError, "unexpected file status")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store a new file on the Shaman server. Note that the Shaman server can
|
// Store a new file on the Shaman server. Note that the Shaman server can
|
||||||
@ -127,23 +119,22 @@ func (f *Flamenco) ShamanFileStore(e echo.Context, checksum string, filesize int
|
|||||||
canDefer, origFilename,
|
canDefer, origFilename,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == fileserver.ErrFileAlreadyExists {
|
switch err {
|
||||||
|
case fileserver.ErrFileAlreadyExists:
|
||||||
return e.String(http.StatusAlreadyReported, "")
|
return e.String(http.StatusAlreadyReported, "")
|
||||||
|
case fileserver.ErrFileShouldDefer:
|
||||||
|
return e.String(http.StatusTooEarly, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Warn().Err(err).Msg("shaman: checking stored file")
|
logger.Warn().Err(err).Msg("shaman: checking stored file")
|
||||||
if sizeErr, ok := err.(fileserver.ErrFileSizeMismatch); ok {
|
|
||||||
return sendAPIError(e, http.StatusExpectationFailed,
|
switch v := err.(type) {
|
||||||
"size mismatch, expected %d bytes, received %d bytes",
|
case fileserver.ErrFileSizeMismatch, fileserver.ErrFileChecksumMismatch:
|
||||||
sizeErr.DeclaredSize, sizeErr.ActualSize)
|
return sendAPIError(e, http.StatusExpectationFailed, v.Error())
|
||||||
}
|
default:
|
||||||
if checksumErr, ok := err.(fileserver.ErrFileChecksumMismatch); ok {
|
|
||||||
return sendAPIError(e, http.StatusExpectationFailed,
|
|
||||||
"checksum mismatch, expected %d bytes, received %d bytes",
|
|
||||||
checksumErr.DeclaredChecksum, checksumErr.ActualChecksum)
|
|
||||||
}
|
|
||||||
return sendAPIError(e, http.StatusInternalServerError, "unexpected error: %v", err)
|
return sendAPIError(e, http.StatusInternalServerError, "unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -344,13 +344,7 @@ paths:
|
|||||||
description: Normal response.
|
description: Normal response.
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema: {$ref: "#/components/schemas/ShamanSingleFileStatus"}
|
||||||
type: object
|
|
||||||
description: Status of a file in the Shaman storage.
|
|
||||||
properties:
|
|
||||||
"status": {$ref: "#/components/schemas/ShamanFileStatus"}
|
|
||||||
required: [status]
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
description: unexpected error
|
description: unexpected error
|
||||||
content:
|
content:
|
||||||
@ -364,6 +358,8 @@ paths:
|
|||||||
Store a new file on the Shaman server. Note that the Shaman server can
|
Store a new file on the Shaman server. Note that the Shaman server can
|
||||||
forcibly close the HTTP connection when another client finishes uploading
|
forcibly close the HTTP connection when another client finishes uploading
|
||||||
the exact same file, to prevent double uploads.
|
the exact same file, to prevent double uploads.
|
||||||
|
|
||||||
|
The file's contents should be sent in the request body.
|
||||||
tags: [shaman]
|
tags: [shaman]
|
||||||
parameters:
|
parameters:
|
||||||
- name: checksum
|
- name: checksum
|
||||||
@ -393,23 +389,28 @@ paths:
|
|||||||
The original filename. If sent along with the request, it will be
|
The original filename. If sent along with the request, it will be
|
||||||
included in the server logs, which can aid in debugging.
|
included in the server logs, which can aid in debugging.
|
||||||
requestBody:
|
requestBody:
|
||||||
description: The file's contents.
|
description: Contents of the file
|
||||||
required: true
|
required: true
|
||||||
content:
|
content:
|
||||||
application/octet-stream:
|
application/octet-stream:
|
||||||
example: Just the contents of any file.
|
schema:
|
||||||
|
type: string
|
||||||
|
format: binary
|
||||||
|
|
||||||
responses:
|
responses:
|
||||||
"204":
|
"204":
|
||||||
description: Checkout was created succesfully.
|
description: The file was accepted.
|
||||||
"208":
|
"208":
|
||||||
description: >
|
description: The file was already known to the server.
|
||||||
The file has already been uploaded. Note that this can also be sent
|
|
||||||
when this file is currently in the process of being uploaded, and
|
|
||||||
`X-Shaman-Can-Defer-Upload: true` was sent in the request.
|
|
||||||
"409":
|
|
||||||
description: Checkout already exists.
|
|
||||||
"417":
|
"417":
|
||||||
description: There was a mismatch between the request parameters and the actual file size or checksum of the uploaded file.
|
description: >
|
||||||
|
There was a mismatch between the request parameters and the actual
|
||||||
|
file size or checksum of the uploaded file.
|
||||||
|
"425":
|
||||||
|
description: >
|
||||||
|
Client should defer uploading this file. The file is currently in
|
||||||
|
the process of being uploaded by someone else, and
|
||||||
|
`X-Shaman-Can-Defer-Upload: true` was sent in the request.
|
||||||
default:
|
default:
|
||||||
description: unexpected error
|
description: unexpected error
|
||||||
content:
|
content:
|
||||||
@ -721,7 +722,8 @@ components:
|
|||||||
properties:
|
properties:
|
||||||
"sha": {type: string, description: "SHA256 checksum of the file"}
|
"sha": {type: string, description: "SHA256 checksum of the file"}
|
||||||
"size": {type: integer, description: "File size in bytes"}
|
"size": {type: integer, description: "File size in bytes"}
|
||||||
required: [sha, size]
|
"path": {type: string, description: "Location of the file in the checkout"}
|
||||||
|
required: [sha, size, path]
|
||||||
|
|
||||||
ShamanFileSpecWithStatus:
|
ShamanFileSpecWithStatus:
|
||||||
allOf:
|
allOf:
|
||||||
@ -730,20 +732,13 @@ components:
|
|||||||
"status": {$ref: "#/components/schemas/ShamanFileStatus"}
|
"status": {$ref: "#/components/schemas/ShamanFileStatus"}
|
||||||
required: [status]
|
required: [status]
|
||||||
|
|
||||||
ShamanFileSpecWithPath:
|
|
||||||
allOf:
|
|
||||||
- $ref: '#/components/schemas/ShamanFileSpec'
|
|
||||||
- properties:
|
|
||||||
"path": {type: string, description: Location of the file in the checkout}
|
|
||||||
required: [path]
|
|
||||||
|
|
||||||
ShamanCheckout:
|
ShamanCheckout:
|
||||||
type: object
|
type: object
|
||||||
description: Set of files with their SHA256 checksum, size in bytes, and desired location in the checkout directory.
|
description: Set of files with their SHA256 checksum, size in bytes, and desired location in the checkout directory.
|
||||||
properties:
|
properties:
|
||||||
"files":
|
"files":
|
||||||
type: array
|
type: array
|
||||||
items: {$ref: "#/components/schemas/ShamanFileSpecWithPath"}
|
items: {$ref: "#/components/schemas/ShamanFileSpec"}
|
||||||
"checkoutPath":
|
"checkoutPath":
|
||||||
type: string
|
type: string
|
||||||
description: >
|
description: >
|
||||||
@ -765,6 +760,13 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
enum: [unknown, uploading, stored]
|
enum: [unknown, uploading, stored]
|
||||||
|
|
||||||
|
ShamanSingleFileStatus:
|
||||||
|
type: object
|
||||||
|
description: Status of a file in the Shaman storage.
|
||||||
|
properties:
|
||||||
|
"status": {$ref: "#/components/schemas/ShamanFileStatus"}
|
||||||
|
required: [status]
|
||||||
|
|
||||||
securitySchemes:
|
securitySchemes:
|
||||||
worker_auth:
|
worker_auth:
|
||||||
description: Username is the worker ID, password is the secret given at worker registration.
|
description: Username is the worker ID, password is the secret given at worker registration.
|
||||||
|
@ -1377,9 +1377,7 @@ func (r ShamanCheckoutRequirementsResponse) StatusCode() int {
|
|||||||
type ShamanFileStoreCheckResponse struct {
|
type ShamanFileStoreCheckResponse struct {
|
||||||
Body []byte
|
Body []byte
|
||||||
HTTPResponse *http.Response
|
HTTPResponse *http.Response
|
||||||
JSON200 *struct {
|
JSON200 *ShamanSingleFileStatus
|
||||||
Status ShamanFileStatus `json:"status"`
|
|
||||||
}
|
|
||||||
JSONDefault *Error
|
JSONDefault *Error
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2028,9 +2026,7 @@ func ParseShamanFileStoreCheckResponse(rsp *http.Response) (*ShamanFileStoreChec
|
|||||||
|
|
||||||
switch {
|
switch {
|
||||||
case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
|
case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
|
||||||
var dest struct {
|
var dest ShamanSingleFileStatus
|
||||||
Status ShamanFileStatus `json:"status"`
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(bodyBytes, &dest); err != nil {
|
if err := json.Unmarshal(bodyBytes, &dest); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,7 @@ type ServerInterface interface {
|
|||||||
// (OPTIONS /shaman/files/{checksum}/{filesize})
|
// (OPTIONS /shaman/files/{checksum}/{filesize})
|
||||||
ShamanFileStoreCheck(ctx echo.Context, checksum string, filesize int) error
|
ShamanFileStoreCheck(ctx echo.Context, checksum string, filesize int) error
|
||||||
// Store a new file on the Shaman server. Note that the Shaman server can forcibly close the HTTP connection when another client finishes uploading the exact same file, to prevent double uploads.
|
// Store a new file on the Shaman server. Note that the Shaman server can forcibly close the HTTP connection when another client finishes uploading the exact same file, to prevent double uploads.
|
||||||
|
// The file's contents should be sent in the request body.
|
||||||
// (POST /shaman/files/{checksum}/{filesize})
|
// (POST /shaman/files/{checksum}/{filesize})
|
||||||
ShamanFileStore(ctx echo.Context, checksum string, filesize int, params ShamanFileStoreParams) error
|
ShamanFileStore(ctx echo.Context, checksum string, filesize int, params ShamanFileStoreParams) error
|
||||||
}
|
}
|
||||||
|
@ -18,92 +18,92 @@ import (
|
|||||||
// Base64 encoded, gzipped, json marshaled Swagger object
|
// Base64 encoded, gzipped, json marshaled Swagger object
|
||||||
var swaggerSpec = []string{
|
var swaggerSpec = []string{
|
||||||
|
|
||||||
"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",
|
||||||
"AP//RfyB4BlUAAA=",
|
"3by5+Z8AAAD//+uKmtshVAAA",
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSwagger returns the content of the embedded swagger specification file
|
// GetSwagger returns the content of the embedded swagger specification file
|
||||||
|
@ -246,11 +246,14 @@ type SecurityError struct {
|
|||||||
type ShamanCheckout struct {
|
type ShamanCheckout struct {
|
||||||
// Path where the Manager should create this checkout, It is relative to the Shaman checkout path as configured on the Manager. In older versions of the Shaman this was just the "checkout ID", but in this version it can be a path like `project-slug/scene-name/unique-ID`.
|
// Path where the Manager should create this checkout, It is relative to the Shaman checkout path as configured on the Manager. In older versions of the Shaman this was just the "checkout ID", but in this version it can be a path like `project-slug/scene-name/unique-ID`.
|
||||||
CheckoutPath string `json:"checkoutPath"`
|
CheckoutPath string `json:"checkoutPath"`
|
||||||
Files []ShamanFileSpecWithPath `json:"files"`
|
Files []ShamanFileSpec `json:"files"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specification of a file in the Shaman storage.
|
// Specification of a file in the Shaman storage.
|
||||||
type ShamanFileSpec struct {
|
type ShamanFileSpec struct {
|
||||||
|
// Location of the file in the checkout
|
||||||
|
Path string `json:"path"`
|
||||||
|
|
||||||
// SHA256 checksum of the file
|
// SHA256 checksum of the file
|
||||||
Sha string `json:"sha"`
|
Sha string `json:"sha"`
|
||||||
|
|
||||||
@ -258,15 +261,6 @@ type ShamanFileSpec struct {
|
|||||||
Size int `json:"size"`
|
Size int `json:"size"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ShamanFileSpecWithPath defines model for ShamanFileSpecWithPath.
|
|
||||||
type ShamanFileSpecWithPath struct {
|
|
||||||
// Embedded struct due to allOf(#/components/schemas/ShamanFileSpec)
|
|
||||||
ShamanFileSpec `yaml:",inline"`
|
|
||||||
// Embedded fields due to inline allOf schema
|
|
||||||
// Location of the file in the checkout
|
|
||||||
Path string `json:"path"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShamanFileSpecWithStatus defines model for ShamanFileSpecWithStatus.
|
// ShamanFileSpecWithStatus defines model for ShamanFileSpecWithStatus.
|
||||||
type ShamanFileSpecWithStatus struct {
|
type ShamanFileSpecWithStatus struct {
|
||||||
// Embedded struct due to allOf(#/components/schemas/ShamanFileSpec)
|
// Embedded struct due to allOf(#/components/schemas/ShamanFileSpec)
|
||||||
@ -288,6 +282,11 @@ type ShamanRequirementsResponse struct {
|
|||||||
Files []ShamanFileSpecWithStatus `json:"files"`
|
Files []ShamanFileSpecWithStatus `json:"files"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Status of a file in the Shaman storage.
|
||||||
|
type ShamanSingleFileStatus struct {
|
||||||
|
Status ShamanFileStatus `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
// Job definition submitted to Flamenco.
|
// Job definition submitted to Flamenco.
|
||||||
type SubmittedJob struct {
|
type SubmittedJob struct {
|
||||||
// Arbitrary metadata strings. More complex structures can be modeled by using `a.b.c` notation for the key.
|
// Arbitrary metadata strings. More complex structures can be modeled by using `a.b.c` notation for the key.
|
||||||
|
@ -16,7 +16,10 @@ func (m *Manager) ReportRequirements(ctx context.Context, requirements api.Shama
|
|||||||
logger := zerolog.Ctx(ctx)
|
logger := zerolog.Ctx(ctx)
|
||||||
logger.Debug().Msg("user requested checkout requirements")
|
logger.Debug().Msg("user requested checkout requirements")
|
||||||
|
|
||||||
missing := api.ShamanRequirementsResponse{}
|
missing := api.ShamanRequirementsResponse{
|
||||||
|
Files: []api.ShamanFileSpecWithStatus{},
|
||||||
|
}
|
||||||
|
|
||||||
alreadyRequested := map[string]bool{}
|
alreadyRequested := map[string]bool{}
|
||||||
for _, fileSpec := range requirements.Files {
|
for _, fileSpec := range requirements.Files {
|
||||||
fileKey := fmt.Sprintf("%s/%d", fileSpec.Sha, fileSpec.Size)
|
fileKey := fmt.Sprintf("%s/%d", fileSpec.Sha, fileSpec.Size)
|
||||||
@ -25,7 +28,7 @@ func (m *Manager) ReportRequirements(ctx context.Context, requirements api.Shama
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
path, status := m.fileStore.ResolveFile(fileSpec.Sha, int64(fileSpec.Size), filestore.ResolveEverything)
|
storePath, status := m.fileStore.ResolveFile(fileSpec.Sha, int64(fileSpec.Size), filestore.ResolveEverything)
|
||||||
|
|
||||||
var apiStatus api.ShamanFileStatus
|
var apiStatus api.ShamanFileStatus
|
||||||
switch status {
|
switch status {
|
||||||
@ -38,13 +41,13 @@ func (m *Manager) ReportRequirements(ctx context.Context, requirements api.Shama
|
|||||||
case filestore.StatusStored:
|
case filestore.StatusStored:
|
||||||
// We expect this file to be sent soon, though, so we need to
|
// We expect this file to be sent soon, though, so we need to
|
||||||
// 'touch' it to make sure it won't be GC'd in the mean time.
|
// 'touch' it to make sure it won't be GC'd in the mean time.
|
||||||
go touchFile(path)
|
go touchFile(storePath)
|
||||||
|
|
||||||
// Only send a response when the caller needs to do something.
|
// Only send a response when the caller needs to do something.
|
||||||
continue
|
continue
|
||||||
default:
|
default:
|
||||||
logger.Error().
|
logger.Error().
|
||||||
Str("path", path).
|
Str("path", fileSpec.Path).
|
||||||
Str("status", status.String()).
|
Str("status", status.String()).
|
||||||
Str("checksum", fileSpec.Sha).
|
Str("checksum", fileSpec.Sha).
|
||||||
Int("filesize", fileSpec.Size).
|
Int("filesize", fileSpec.Size).
|
||||||
|
@ -34,13 +34,13 @@ func TestReportRequirements(t *testing.T) {
|
|||||||
manager, cleanup := createTestManager()
|
manager, cleanup := createTestManager()
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
|
spec1 := api.ShamanFileSpec{Sha: "63b72c63b9424fd13b9370fb60069080c3a15717cf3ad442635b187c6a895079", Size: 127, Path: "file1.txt"}
|
||||||
|
spec2 := api.ShamanFileSpec{Sha: "9f1470441beb98dbb66e3339e7da697d9c2312999a6a5610c461cbf55040e210", Size: 795, Path: "file2.txt"}
|
||||||
|
spec3 := api.ShamanFileSpec{Sha: "59c6bd72af62aa860343adcafd46e3998934a9db2997ce08514b4361f099fa58", Size: 1134, Path: "file3.txt"}
|
||||||
|
spec4 := api.ShamanFileSpec{Sha: "59c6bd72af62aa860343adcafd46e3998934a9db2997ce08514b4361f099fa58", Size: 1134, Path: "file4.txt"} // duplicate of the above
|
||||||
|
|
||||||
required := api.ShamanRequirementsRequest{
|
required := api.ShamanRequirementsRequest{
|
||||||
Files: []api.ShamanFileSpec{
|
Files: []api.ShamanFileSpec{spec1, spec2, spec3, spec4},
|
||||||
{"63b72c63b9424fd13b9370fb60069080c3a15717cf3ad442635b187c6a895079", 127},
|
|
||||||
{"9f1470441beb98dbb66e3339e7da697d9c2312999a6a5610c461cbf55040e210", 795},
|
|
||||||
{"59c6bd72af62aa860343adcafd46e3998934a9db2997ce08514b4361f099fa58", 1134},
|
|
||||||
{"59c6bd72af62aa860343adcafd46e3998934a9db2997ce08514b4361f099fa58", 1134}, // duplicate of the above
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := manager.ReportRequirements(context.Background(), required)
|
response, err := manager.ReportRequirements(context.Background(), required)
|
||||||
@ -49,9 +49,9 @@ func TestReportRequirements(t *testing.T) {
|
|||||||
// We should not be required to upload the same file twice, so the duplicate
|
// We should not be required to upload the same file twice, so the duplicate
|
||||||
// should not be in the response.
|
// should not be in the response.
|
||||||
assert.Equal(t, []api.ShamanFileSpecWithStatus{
|
assert.Equal(t, []api.ShamanFileSpecWithStatus{
|
||||||
{api.ShamanFileSpec{"63b72c63b9424fd13b9370fb60069080c3a15717cf3ad442635b187c6a895079", 127}, api.ShamanFileStatusUnknown},
|
{ShamanFileSpec: spec1, Status: api.ShamanFileStatusUnknown},
|
||||||
{api.ShamanFileSpec{"9f1470441beb98dbb66e3339e7da697d9c2312999a6a5610c461cbf55040e210", 795}, api.ShamanFileStatusUnknown},
|
{ShamanFileSpec: spec2, Status: api.ShamanFileStatusUnknown},
|
||||||
{api.ShamanFileSpec{"59c6bd72af62aa860343adcafd46e3998934a9db2997ce08514b4361f099fa58", 1134}, api.ShamanFileStatusUnknown},
|
{ShamanFileSpec: spec3, Status: api.ShamanFileStatusUnknown},
|
||||||
}, response.Files)
|
}, response.Files)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +38,11 @@ import (
|
|||||||
// uploaded the same file at the same time.
|
// uploaded the same file at the same time.
|
||||||
var ErrFileAlreadyExists = errors.New("uploaded file already exists")
|
var ErrFileAlreadyExists = errors.New("uploaded file already exists")
|
||||||
|
|
||||||
|
// ErrFileShouldDefer indicates that the file is currently being uploaded
|
||||||
|
// already. This will only be returned when the caller indicates the client is
|
||||||
|
// capable of deferring the upload.
|
||||||
|
var ErrFileShouldDefer = errors.New("file is being uploaded by someone else")
|
||||||
|
|
||||||
type ErrFileSizeMismatch struct {
|
type ErrFileSizeMismatch struct {
|
||||||
DeclaredSize int64
|
DeclaredSize int64
|
||||||
ActualSize int64
|
ActualSize int64
|
||||||
@ -59,14 +64,15 @@ func (e ErrFileChecksumMismatch) Error() string {
|
|||||||
// ReceiveFile streams a file from a HTTP request to disk.
|
// ReceiveFile streams a file from a HTTP request to disk.
|
||||||
func (fs *FileServer) ReceiveFile(
|
func (fs *FileServer) ReceiveFile(
|
||||||
ctx context.Context, bodyReader io.ReadCloser,
|
ctx context.Context, bodyReader io.ReadCloser,
|
||||||
checksum string, filesize int64, canDefer bool,
|
checksum string, filesize int64,
|
||||||
|
canDefer bool, originalFilename string,
|
||||||
) error {
|
) error {
|
||||||
logger := *zerolog.Ctx(ctx)
|
logger := *zerolog.Ctx(ctx)
|
||||||
defer bodyReader.Close()
|
defer bodyReader.Close()
|
||||||
|
|
||||||
localPath, status := fs.fileStore.ResolveFile(checksum, filesize, filestore.ResolveEverything)
|
storePath, status := fs.fileStore.ResolveFile(checksum, filesize, filestore.ResolveEverything)
|
||||||
logger = logger.With().
|
logger = logger.With().
|
||||||
Str("path", localPath).
|
Str("path", originalFilename).
|
||||||
Str("checksum", checksum).
|
Str("checksum", checksum).
|
||||||
Int64("filesize", filesize).
|
Int64("filesize", filesize).
|
||||||
Str("status", status.String()).
|
Str("status", status.String()).
|
||||||
@ -74,12 +80,12 @@ func (fs *FileServer) ReceiveFile(
|
|||||||
|
|
||||||
switch status {
|
switch status {
|
||||||
case filestore.StatusStored:
|
case filestore.StatusStored:
|
||||||
logger.Info().Msg("shaman: uploaded file already exists")
|
logger.Info().Str("storePath", storePath).Msg("shaman: uploaded file already exists")
|
||||||
return ErrFileAlreadyExists
|
return ErrFileAlreadyExists
|
||||||
case filestore.StatusUploading:
|
case filestore.StatusUploading:
|
||||||
if canDefer {
|
if canDefer {
|
||||||
logger.Info().Msg("shaman: someone is uploading this file and client can defer")
|
logger.Info().Str("storePath", storePath).Msg("shaman: someone is uploading this file and client can defer")
|
||||||
return ErrFileAlreadyExists
|
return ErrFileShouldDefer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ func TestStoreFile(t *testing.T) {
|
|||||||
|
|
||||||
testWithChecksum := func(checksum string, reportSize int64) error {
|
testWithChecksum := func(checksum string, reportSize int64) error {
|
||||||
buffer := io.NopCloser(bytes.NewBuffer(payload))
|
buffer := io.NopCloser(bytes.NewBuffer(payload))
|
||||||
return server.ReceiveFile(context.Background(), buffer, checksum, reportSize, false)
|
return server.ReceiveFile(context.Background(), buffer, checksum, reportSize, false, "testfile.txt")
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
@ -154,8 +154,10 @@ func (s *Store) MoveToStored(checksum string, filesize int64, uploadedFilePath s
|
|||||||
func (s *Store) removeFile(filePath string) error {
|
func (s *Store) removeFile(filePath string) error {
|
||||||
err := os.Remove(filePath)
|
err := os.Remove(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
log.Debug().Err(err).Msg("shaman: unable to delete file; ignoring")
|
log.Debug().Err(err).Msg("shaman: unable to delete file; ignoring")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Clean up directory structure, but ignore any errors (dirs may not be empty)
|
// Clean up directory structure, but ignore any errors (dirs may not be empty)
|
||||||
directory := path.Dir(filePath)
|
directory := path.Dir(filePath)
|
||||||
|
@ -148,7 +148,7 @@ func (s *Server) FileStoreCheck(ctx context.Context, checksum string, filesize i
|
|||||||
// early when another client finishes uploading the exact same file, to prevent
|
// early when another client finishes uploading the exact same file, to prevent
|
||||||
// double uploads.
|
// double uploads.
|
||||||
func (s *Server) FileStore(ctx context.Context, file io.ReadCloser, checksum string, filesize int64, canDefer bool, originalFilename string) error {
|
func (s *Server) FileStore(ctx context.Context, file io.ReadCloser, checksum string, filesize int64, canDefer bool, originalFilename string) error {
|
||||||
err := s.fileServer.ReceiveFile(ctx, file, checksum, filesize, canDefer)
|
err := s.fileServer.ReceiveFile(ctx, file, checksum, filesize, canDefer, originalFilename)
|
||||||
// TODO: Maybe translate this error into something that can be understood by
|
// TODO: Maybe translate this error into something that can be understood by
|
||||||
// the caller without relying on types declared in the `fileserver` package?
|
// the caller without relying on types declared in the `fileserver` package?
|
||||||
return err
|
return err
|
||||||
|
Loading…
x
Reference in New Issue
Block a user