Skip to content

Workfiles: Add basic workfiles api #1275

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 52 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
3bfb11d
moved interfaces to subfolder
iLLiCiTiT Apr 25, 2025
28eaf12
move exception into separate file
iLLiCiTiT Apr 25, 2025
9d0d830
move workfiles interface to separate file
iLLiCiTiT Apr 25, 2025
9e1e36c
remove ABC form 'IWorkfileHost'
iLLiCiTiT Apr 25, 2025
7e5d861
remove validation of methods
iLLiCiTiT Apr 25, 2025
9140d11
added helper data structure for colleting workfiles
iLLiCiTiT Apr 25, 2025
156eb14
remove unnecessary 'work_root'
iLLiCiTiT Apr 25, 2025
fe28391
add new line char at the end
iLLiCiTiT Apr 25, 2025
515cd79
first implementation of list workfiles
iLLiCiTiT Apr 25, 2025
152211a
'get_workfile_extensions' is not abstract anymore
iLLiCiTiT Apr 28, 2025
d78e25c
added helper function to collect comments from existing workfiles
iLLiCiTiT Apr 28, 2025
615529f
added 'WorkfileInfo' to host public api
iLLiCiTiT Apr 28, 2025
a61a94d
added more helper functions to workfile path mapping
iLLiCiTiT Apr 28, 2025
b5f8997
selection cares about more information
iLLiCiTiT Apr 28, 2025
1037776
pass project settings to template key getter
iLLiCiTiT Apr 28, 2025
4220f92
pass host name to template data getter
iLLiCiTiT Apr 28, 2025
67f478d
modified controller base
iLLiCiTiT Apr 28, 2025
ea12998
use only IWorkfileHost methods
iLLiCiTiT Apr 28, 2025
f5c8f01
pass host to workfiles model
iLLiCiTiT Apr 28, 2025
326a182
updated 'set_selected_workfile_path'
iLLiCiTiT Apr 28, 2025
ad7b2c4
more methods requiring 'IWorkfileHost'
iLLiCiTiT Apr 28, 2025
ec579ca
updated controller arguments to match needs
iLLiCiTiT Apr 28, 2025
16b29a6
added reset to workfile model
iLLiCiTiT Apr 28, 2025
085f4cb
added more cache items
iLLiCiTiT Apr 28, 2025
1211a71
move private methods below public ones
iLLiCiTiT Apr 28, 2025
a2dad64
move public methods above private
iLLiCiTiT Apr 28, 2025
0f64ab1
remove unused method
iLLiCiTiT Apr 28, 2025
5fe625a
remove more unnecessary methods
iLLiCiTiT Apr 28, 2025
f4961bc
updated workarea model
iLLiCiTiT Apr 28, 2025
98acfd8
updated entities model
iLLiCiTiT Apr 28, 2025
60c2c4e
move public method above private
iLLiCiTiT Apr 28, 2025
e4f6342
implement 'get_workfile_entities' on controller
iLLiCiTiT Apr 28, 2025
b8b012d
updated UI to work with new methods and structures
iLLiCiTiT Apr 28, 2025
e705358
fix abstract property
iLLiCiTiT Apr 28, 2025
95b1820
added some typehints into IWorkfileHost
iLLiCiTiT Apr 28, 2025
bef56a5
added todos into controller
iLLiCiTiT Apr 28, 2025
552bc03
added comment
iLLiCiTiT Apr 28, 2025
80397a3
implemented base of published workfile collection
iLLiCiTiT Apr 29, 2025
dde5c6a
use collect published files from host
iLLiCiTiT Apr 30, 2025
b76ae8f
update controller
iLLiCiTiT Apr 30, 2025
1b7474b
Merge workfile entities model into workfiles model
iLLiCiTiT Apr 30, 2025
2f6ed06
Remove publish workfiles model
iLLiCiTiT Apr 30, 2025
eb33281
merge workfile models into one
iLLiCiTiT Apr 30, 2025
6a7f41f
move workfiles related logic to workfiles model
iLLiCiTiT Apr 30, 2025
21c1a8b
added base implementation to workfiles interface
iLLiCiTiT May 16, 2025
29d824d
modified change current context function
iLLiCiTiT May 16, 2025
f4638b9
implemented utils functions for workfiles
iLLiCiTiT May 16, 2025
6390879
modified workfiles tool accordingly
iLLiCiTiT May 16, 2025
723463d
use correct function
iLLiCiTiT May 16, 2025
a37c074
expect entities instead of ids
iLLiCiTiT May 19, 2025
36aae5a
Merge branch 'develop' into enhancement/enhance-workfile-api
iLLiCiTiT May 19, 2025
70f3c05
linting fixes
iLLiCiTiT May 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions client/ayon_core/host/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

from .interfaces import (
IWorkfileHost,
WorkfileInfo,
PublishedWorkfileInfo,
ILoadHost,
IPublishHost,
INewPublisher,
Expand All @@ -16,6 +18,8 @@
"HostBase",

"IWorkfileHost",
"WorkfileInfo",
"PublishedWorkfileInfo",
"ILoadHost",
"IPublishHost",
"INewPublisher",
Expand Down
5 changes: 3 additions & 2 deletions client/ayon_core/host/host.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
import logging
import contextlib
from abc import ABC, abstractproperty
from abc import ABC, abstractmethod

# NOTE can't import 'typing' because of issues in Maya 2020
# - shiboken crashes on 'typing' module import
Expand Down Expand Up @@ -92,7 +92,8 @@ def log(self):
self._log = logging.getLogger(self.__class__.__name__)
return self._log

@abstractproperty
@property
@abstractmethod
def name(self):
"""Host name."""

Expand Down
20 changes: 20 additions & 0 deletions client/ayon_core/host/interfaces/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from .exceptions import MissingMethodsError
from .workfiles import IWorkfileHost, WorkfileInfo, PublishedWorkfileInfo
from .interfaces import (
IPublishHost,
INewPublisher,
ILoadHost,
)


__all__ = (
"MissingMethodsError",

"IWorkfileHost",
"WorkfileInfo",
"PublishedWorkfileInfo",

"IPublishHost",
"INewPublisher",
"ILoadHost",
)
15 changes: 15 additions & 0 deletions client/ayon_core/host/interfaces/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class MissingMethodsError(ValueError):
"""Exception when host miss some required methods for specific workflow.

Args:
host (HostBase): Host implementation where are missing methods.
missing_methods (list[str]): List of missing methods.
"""

def __init__(self, host, missing_methods):
joined_missing = ", ".join(
['"{}"'.format(item) for item in missing_methods]
)
super().__init__(
f"Host \"{host.name}\" miss methods {joined_missing}"
)
Original file line number Diff line number Diff line change
@@ -1,28 +1,6 @@
from abc import ABC, abstractmethod
from abc import abstractmethod


class MissingMethodsError(ValueError):
"""Exception when host miss some required methods for specific workflow.

Args:
host (HostBase): Host implementation where are missing methods.
missing_methods (list[str]): List of missing methods.
"""

def __init__(self, host, missing_methods):
joined_missing = ", ".join(
['"{}"'.format(item) for item in missing_methods]
)
host_name = getattr(host, "name", None)
if not host_name:
try:
host_name = host.__file__.replace("\\", "/").split("/")[-3]
except Exception:
host_name = str(host)
message = (
"Host \"{}\" miss methods {}".format(host_name, joined_missing)
)
super(MissingMethodsError, self).__init__(message)
from .exceptions import MissingMethodsError


class ILoadHost:
Expand Down Expand Up @@ -105,181 +83,6 @@ def ls(self):
return self.get_containers()


class IWorkfileHost(ABC):
"""Implementation requirements to be able use workfile utils and tool."""

@staticmethod
def get_missing_workfile_methods(host):
"""Look for missing methods on "old type" host implementation.

Method is used for validation of implemented functions related to
workfiles. Checks only existence of methods.

Args:
Union[ModuleType, HostBase]: Object of host where to look for
required methods.

Returns:
list[str]: Missing method implementations for workfiles workflow.
"""

if isinstance(host, IWorkfileHost):
return []

required = [
"open_file",
"save_file",
"current_file",
"has_unsaved_changes",
"file_extensions",
"work_root",
]
missing = []
for name in required:
if not hasattr(host, name):
missing.append(name)
return missing

@staticmethod
def validate_workfile_methods(host):
"""Validate methods of "old type" host for workfiles workflow.

Args:
Union[ModuleType, HostBase]: Object of host to validate.

Raises:
MissingMethodsError: If there are missing methods on host
implementation.
"""

missing = IWorkfileHost.get_missing_workfile_methods(host)
if missing:
raise MissingMethodsError(host, missing)

@abstractmethod
def get_workfile_extensions(self):
"""Extensions that can be used as save.

Questions:
This could potentially use 'HostDefinition'.
"""

return []

@abstractmethod
def save_workfile(self, dst_path=None):
"""Save currently opened scene.

Args:
dst_path (str): Where the current scene should be saved. Or use
current path if 'None' is passed.
"""

pass

@abstractmethod
def open_workfile(self, filepath):
"""Open passed filepath in the host.

Args:
filepath (str): Path to workfile.
"""

pass

@abstractmethod
def get_current_workfile(self):
"""Retrieve path to current opened file.

Returns:
str: Path to file which is currently opened.
None: If nothing is opened.
"""

return None

def workfile_has_unsaved_changes(self):
"""Currently opened scene is saved.

Not all hosts can know if current scene is saved because the API of
DCC does not support it.

Returns:
bool: True if scene is saved and False if has unsaved
modifications.
None: Can't tell if workfiles has modifications.
"""

return None

def work_root(self, session):
"""Modify workdir per host.

Default implementation keeps workdir untouched.

Warnings:
We must handle this modification with more sophisticated way
because this can't be called out of DCC so opening of last workfile
(calculated before DCC is launched) is complicated. Also breaking
defined work template is not a good idea.
Only place where it's really used and can make sense is Maya. There
workspace.mel can modify subfolders where to look for maya files.

Args:
session (dict): Session context data.

Returns:
str: Path to new workdir.
"""

return session["AYON_WORKDIR"]

# --- Deprecated method names ---
def file_extensions(self):
"""Deprecated variant of 'get_workfile_extensions'.

Todo:
Remove when all usages are replaced.
"""
return self.get_workfile_extensions()

def save_file(self, dst_path=None):
"""Deprecated variant of 'save_workfile'.

Todo:
Remove when all usages are replaced.
"""

self.save_workfile(dst_path)

def open_file(self, filepath):
"""Deprecated variant of 'open_workfile'.

Todo:
Remove when all usages are replaced.
"""

return self.open_workfile(filepath)

def current_file(self):
"""Deprecated variant of 'get_current_workfile'.

Todo:
Remove when all usages are replaced.
"""

return self.get_current_workfile()

def has_unsaved_changes(self):
"""Deprecated variant of 'workfile_has_unsaved_changes'.

Todo:
Remove when all usages are replaced.
"""

return self.workfile_has_unsaved_changes()


class IPublishHost:
"""Functions related to new creation system in new publisher.

Expand Down
Loading
Loading