Bases: HoudiniExtractorPlugin
Extractor copying files from last published to staging directory.
It works only if instance data includes "last_version_published_files" and there are frames to fix.
The files from last published are based on files which will be extended/fixed for specific frames.
NOTE
This plugin is closely taken from ayon-nuke. It contains some Houdini addon specific logic as various addons may have unique methods for managing staging_dir
, expectedFiles
and frames
.
TODO: It's preferable to to generalize this plugin for broader use and integrate it into ayon-core.
Source code in client/ayon_houdini/plugins/publish/extract_last_published.py
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126 | class ExtractLastPublished(plugin.HoudiniExtractorPlugin):
"""Extractor copying files from last published to staging directory.
It works only if instance data includes "last_version_published_files"
and there are frames to fix.
The files from last published are based on files which will be
extended/fixed for specific frames.
NOTE:
This plugin is closely taken from ayon-nuke.
It contains some Houdini addon specific logic as various addons may
have unique methods for managing `staging_dir`, `expectedFiles`
and `frames`.
TODO:
It's preferable to to generalize this plugin for broader use and
integrate it into ayon-core.
"""
order = pyblish.api.ExtractorOrder - 0.1
label = "Extract Last Published"
targets = ["local"] # Same target as `CollectFramesFixDef`
families = ["*"]
def process(self, instance):
frames_to_fix = instance.data.get("frames_to_fix")
if not frames_to_fix:
self.log.debug("Skipping, No frames to fix.")
return
if not instance.data.get("integrate", True):
self.log.debug("Skipping collecting frames to fix data for "
"instance because instance is set to not integrate")
return
last_published = instance.data.get("last_version_published_files")
if not last_published:
self.log.debug("Skipping, No last publish found.")
return
last_published_and_frames = collect_frames(last_published)
if not all(last_published_and_frames.values()):
self.log.debug("Skipping, No file sequence found in the "
"last version published files.")
return
staging_dir, expected_filenames = (
self.get_expected_files_and_staging_dir(instance)
)
os.makedirs(staging_dir, exist_ok=True)
expected_and_frames = collect_frames(expected_filenames)
frames_and_expected = {v: k for k, v in expected_and_frames.items()}
frames_to_fix = clique.parse(frames_to_fix, "{ranges}")
anatomy = instance.context.data["anatomy"]
# TODO: This currently copies ALL frames from the last version instead
# of only those within the frame range we're currently looking to
# publish. It should instead, iterate over all expected frames for
# current instance, exclude all "to fix" frames and copy the
# other existing ones.
for file_path, frame in last_published_and_frames.items():
if frame is None:
continue
file_path = anatomy.fill_root(file_path)
if not os.path.exists(file_path):
continue
target_file_name = frames_and_expected.get(frame)
if not target_file_name:
continue
out_path = os.path.join(staging_dir, target_file_name)
# Copy only the frames that we won't render.
if frame and frame not in frames_to_fix:
self.log.debug(f"Copying '{file_path}' -> '{out_path}'")
shutil.copy(file_path, out_path)
def get_expected_files_and_staging_dir(self, instance):
"""Get expected file names or frames.
This method includes Houdini specific code.
Args:
instance (pyblish.api.Instance): The instance to publish.
Returns:
tuple[str, list[str]]: A 2-tuple of staging dir and the list of
expected frames for the current publish instance.
"""
expected_filenames = []
staging_dir = instance.data.get("stagingDir")
expected_files = instance.data.get("expectedFiles", [])
# 'expectedFiles' are preferred over 'frames'
if expected_files:
# Products with expected files
# This can be Render products or submitted cache to farm.
for expected in expected_files:
# expected.values() is a list of lists
expected_filenames.extend(sum(expected.values(), []))
else:
# Products with frames or single file.
frames = instance.data.get("frames", "")
if isinstance(frames, str):
# single file.
expected_filenames.append("{}/{}".format(staging_dir, frames))
else:
# list of frame.
expected_filenames.extend(
["{}/{}".format(staging_dir, f) for f in frames]
)
return staging_dir, expected_filenames
|
get_expected_files_and_staging_dir(instance)
Get expected file names or frames.
This method includes Houdini specific code.
Parameters:
Name | Type | Description | Default |
instance | Instance | | required |
Returns:
Type | Description |
| tuple[str, list[str]]: A 2-tuple of staging dir and the list of expected frames for the current publish instance. |
Source code in client/ayon_houdini/plugins/publish/extract_last_published.py
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126 | def get_expected_files_and_staging_dir(self, instance):
"""Get expected file names or frames.
This method includes Houdini specific code.
Args:
instance (pyblish.api.Instance): The instance to publish.
Returns:
tuple[str, list[str]]: A 2-tuple of staging dir and the list of
expected frames for the current publish instance.
"""
expected_filenames = []
staging_dir = instance.data.get("stagingDir")
expected_files = instance.data.get("expectedFiles", [])
# 'expectedFiles' are preferred over 'frames'
if expected_files:
# Products with expected files
# This can be Render products or submitted cache to farm.
for expected in expected_files:
# expected.values() is a list of lists
expected_filenames.extend(sum(expected.values(), []))
else:
# Products with frames or single file.
frames = instance.data.get("frames", "")
if isinstance(frames, str):
# single file.
expected_filenames.append("{}/{}".format(staging_dir, frames))
else:
# list of frame.
expected_filenames.extend(
["{}/{}".format(staging_dir, f) for f in frames]
)
return staging_dir, expected_filenames
|