Skip to content

extract_rop

ExtractROP

Bases: HoudiniExtractorPlugin

Generic Extractor for any ROP node.

Source code in client/ayon_houdini/plugins/publish/extract_rop.py
 9
10
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
class ExtractROP(plugin.HoudiniExtractorPlugin):
    """Generic Extractor for any ROP node."""
    label = "Extract ROP"
    order = pyblish.api.ExtractorOrder

    families = ["abc", "camera", "bgeo", "pointcache", "fbx",
                "vdbcache", "ass", "redshiftproxy", "mantraifd"]
    targets = ["local", "remote"]

    def process(self, instance: pyblish.api.Instance):
        if instance.data.get("farm"):
            self.log.debug("Should be processed on farm, skipping.")
            return
        creator_attribute = instance.data["creator_attributes"]

        files = instance.data["frames"]
        first_file = files[0] if isinstance(files, (list, tuple)) else files
        _, ext = splitext(
            first_file, allowed_multidot_extensions=[
                ".ass.gz", ".bgeo.sc", ".bgeo.gz",
                ".bgeo.lzma", ".bgeo.bz2"]
        )
        ext = ext.lstrip(".")

        # Value `local` is used as a fallback if the `render_target`
        #   key is missing.
        # This key might be absent because render targets are not
        #   yet implemented for all product types that use this plugin.
        if creator_attribute.get("render_target", "local") == "local":
            self.render_rop(instance)
        self.validate_expected_frames(instance)

        # In some cases representation name is not the the extension
        # TODO: Preferably we remove this very specific naming
        product_type = instance.data["productType"]
        name = {
            "bgeo": "bgeo",
            "rs": "rs",
            "ass": "ass"
        }.get(product_type, ext)

        representation = {
            "name": name,
            "ext": ext,
            "files": instance.data["frames"],
            "stagingDir": instance.data["stagingDir"],
            "frameStart": instance.data["frameStartHandle"],
            "frameEnd": instance.data["frameEndHandle"],
        }
        self.update_representation_data(instance, representation)
        instance.data.setdefault("representations", []).append(representation)

    def validate_expected_frames(self, instance: pyblish.api.Instance):
        """
        Validate all expected files in `instance.data["frames"]` exist in
        the staging directory.
        """
        filenames = instance.data["frames"]
        staging_dir = instance.data["stagingDir"]
        if isinstance(filenames, str):
            # Single frame
            filenames = [filenames]

        missing_frames = []
        for filename in filenames:
            filename = os.path.join(staging_dir, filename)
            if not os.path.isfile(filename):
                missing_frames.append(filename)

        if missing_frames:
            # Combine collections for simpler logs of missing files
            missing_frames  = format_as_collections(missing_frames)
            missing_frames = "\n ".join(
                f"- {sequence}" for sequence in missing_frames
            )
            raise PublishError(
                "Failed to complete render extraction.\n"
                "Please render any missing output files.",
                detail=f"Missing output files: \n {missing_frames}"
            )

    def update_representation_data(self,
                                   instance: pyblish.api.Instance,
                                   representation: dict):
        """Allow subclass to override the representation data in-place"""
        pass

update_representation_data(instance, representation)

Allow subclass to override the representation data in-place

Source code in client/ayon_houdini/plugins/publish/extract_rop.py
90
91
92
93
94
def update_representation_data(self,
                               instance: pyblish.api.Instance,
                               representation: dict):
    """Allow subclass to override the representation data in-place"""
    pass

validate_expected_frames(instance)

Validate all expected files in instance.data["frames"] exist in the staging directory.

Source code in client/ayon_houdini/plugins/publish/extract_rop.py
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
def validate_expected_frames(self, instance: pyblish.api.Instance):
    """
    Validate all expected files in `instance.data["frames"]` exist in
    the staging directory.
    """
    filenames = instance.data["frames"]
    staging_dir = instance.data["stagingDir"]
    if isinstance(filenames, str):
        # Single frame
        filenames = [filenames]

    missing_frames = []
    for filename in filenames:
        filename = os.path.join(staging_dir, filename)
        if not os.path.isfile(filename):
            missing_frames.append(filename)

    if missing_frames:
        # Combine collections for simpler logs of missing files
        missing_frames  = format_as_collections(missing_frames)
        missing_frames = "\n ".join(
            f"- {sequence}" for sequence in missing_frames
        )
        raise PublishError(
            "Failed to complete render extraction.\n"
            "Please render any missing output files.",
            detail=f"Missing output files: \n {missing_frames}"
        )