Skip to content

pre_launch_install_ayon_extension

InstallAyonExtensionToPremiere

Bases: PreLaunchHook

Automatically 'installs' the AYON Premiere extension.

Checks if Premiere already has the extension in the relevant folder, will try to create that folder and unzip the extension if not.

Source code in client/ayon_premiere/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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
class InstallAyonExtensionToPremiere(PreLaunchHook):
    """
    Automatically 'installs' the AYON Premiere extension.

    Checks if Premiere already has the extension in the relevant folder,
    will try to create that folder and unzip the extension if not.
    """

    app_groups = {"premiere"}

    order = 1
    launch_types = {LaunchTypes.local}

    def execute(self):
        try:
            settings = self.data["project_settings"]["premiere"]
            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 Premiere 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"], r"Adobe\CEP\extensions\io.ynput.PPRO.panel"
        )

        extension_path = os.path.join(
            PREMIERE_ADDON_ROOT,
            r"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

        try:
            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")

        except OSError as error:
            self.log.warning(f"OS error has occured: {error}")

        except PermissionError as error:
            self.log.warning(f"Permissions error has occured: {error}")

        except Exception as error:
            self.log.warning(f"An unexpected error occured: {error}")

    def _compare_extension_versions(
        self, target_path: str, extension_path: str
    ) -> bool:
        try:
            # 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

        except PermissionError as error:
            self.log.warning(
                "Permissions error has occurred while comparing "
                f"versions: {error}"
            )
            return False

        except OSError as error:
            self.log.warning(
                f"OS error has occured while comparing versions: {error}"
            )
            return False

        except Exception as error:
            self.log.warning(
                f"An unexpected error occured when comparing version: {error}"
            )
            return False