Skip to content

pre_launch_install_ayon_extension

InstallAyonExtensionToAfterEffect

Bases: PreLaunchHook

Automatically 'installs' the AYON AfterEffects extension.

Checks if AE already has the extension in the relevant folder, will try to create that folder and unzip the extension if not. Will compare versions if folder does exist, replacing if mismatched.

Source code in client/ayon_aftereffects/hooks/pre_launch_install_ayon_extension.py
 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
class InstallAyonExtensionToAfterEffect(PreLaunchHook):
    """
    Automatically 'installs' the AYON AfterEffects extension.

    Checks if AE already has the extension in the relevant folder,
    will try to create that folder and unzip the extension if not.
    Will compare versions if folder does exist, replacing if mismatched.
    """

    app_groups = {"aftereffects"}

    order = 1
    launch_types = {LaunchTypes.local}

    def execute(self):
        try:
            settings = self.data["project_settings"]["aftereffects"]
            if not settings["auto_install_extension"]:
                return
            self.inner_execute()

        except Exception:
            self.log.warning(
                "Processing of {} crashed.".format(self.__class__.__name__),
                exc_info=True,
            )

    def inner_execute(self):
        self.log.info("Installing AYON After Effects extension.")

        # Windows only for now.
        if not platform.system().lower() == "windows":
            self.log.info("Non Windows platform. Cancelling..")
            return

        target_path = os.path.join(
            os.environ["appdata"],
            "Adobe",
            "CEP",
            "extensions",
            "io.ynput.AE.panel",
        )

        extension_path = os.path.join(
            AFTEREFFECTS_ADDON_ROOT,
            "api",
            "extension.zxp",
        )

        # Extension already installed, compare the versions
        if os.path.exists(target_path):
            self.log.info(
                f"The extension already exists at: {target_path}. "
                f"Comparing versions.."
            )
            if not self._compare_extension_versions(
                target_path, extension_path
            ):
                return

        self.log.debug(f"Creating directory: {target_path}")
        os.makedirs(target_path, exist_ok=True)

        with ZipFile(extension_path, "r") as archive:
            archive.extractall(path=target_path)

        self.log.info("Successfully installed AYON extension")

    def _compare_extension_versions(
        self, target_path: str, extension_path: str
    ) -> bool:
        # opens the existing extension manifest to get the Version attr
        with open(f"{target_path}/CSXS/manifest.xml", "rb") as xml_file:
            installed_version = (
                ET.parse(xml_file)
                .getroot()
                .attrib.get("ExtensionBundleVersion")
            )
        self.log.debug(f"Current extension version found: {installed_version}")

        if not installed_version:
            self.log.warning(
                "Unable to resolve the currently installed extension "
                "version. Cancelling.."
            )
            return False

        # opens the .zxp manifest to get the Version attribute.
        with ZipFile(extension_path, "r") as archive:
            xml_file = archive.open("CSXS/manifest.xml")

        new_version = (
            ET.parse(xml_file).getroot().attrib.get("ExtensionBundleVersion")
        )
        if not new_version:
            self.log.warning(
                "Unable to resolve the new extension version. " "Cancelling.."
            )
        self.log.debug(f"New extension version found: {new_version}")

        # compare the two versions, a simple == is enough since
        # we don't care if the version increments or decrements
        # if they match nothing happens.
        if installed_version == new_version:
            self.log.info("Versions matched. Cancelling..")
            return False

        # remove the existing addon
        self.log.info("Version mismatch found. Removing old extensions..")
        rmtree(target_path)
        return True