Skip to content

Commit

Permalink
Merge pull request #6 from Sponge96/install-hook
Browse files Browse the repository at this point in the history
pre launch hook for installing AYON extension
  • Loading branch information
kalisp authored Jan 22, 2025
2 parents b20a7d2 + 68f3b87 commit bae8ed6
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 7 deletions.
Binary file modified client/ayon_premiere/api/extension.zxp
Binary file not shown.
2 changes: 1 addition & 1 deletion client/ayon_premiere/api/extension/CSXS/manifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
ExtensionBundleName="io.ynput.PPRO.panel"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ExtensionList>
<Extension Id="io.ynput.PPRO.panel" Version="1.0.0" />
<Extension Id="io.ynput.PPRO.panel" />
</ExtensionList>
<ExecutionEnvironment>
<HostList>
Expand Down
153 changes: 153 additions & 0 deletions client/ayon_premiere/hooks/pre_launch_install_ayon_extension.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import os
import platform
from zipfile import ZipFile
import xml.etree.ElementTree as ET
from shutil import rmtree


from ayon_premiere import PREMIERE_ADDON_ROOT
from ayon_applications import PreLaunchHook, LaunchTypes


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"][self.host_name]
if not settings["hooks"]["InstallAyonExtensionToPremiere"][
"enabled"
]:
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
4 changes: 2 additions & 2 deletions server/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

from ayon_server.addons import BaseServerAddon

from .settings import MySettings, DEFAULT_VALUES
from .settings import PremiereSettings, DEFAULT_VALUES


class MyAddon(BaseServerAddon):
settings_model: Type[MySettings] = MySettings
settings_model: Type[PremiereSettings] = PremiereSettings

async def get_default_settings(self):
settings_model_cls = self.get_settings_model()
Expand Down
28 changes: 24 additions & 4 deletions server/settings.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@
from ayon_server.settings import BaseSettingsModel
from ayon_server.settings import BaseSettingsModel, SettingsField

DEFAULT_VALUES = {}

class HookOptionalModel(BaseSettingsModel):
enabled: bool = SettingsField(False, title="Enabled")

class MySettings(BaseSettingsModel):
pass

class HooksModel(BaseSettingsModel):
InstallAyonExtensionToPremiere: HookOptionalModel = SettingsField(
default_factory=HookOptionalModel,
title="Install AYON Extension",
)


class PremiereSettings(BaseSettingsModel):
hooks: HooksModel = SettingsField(
default_factory=HooksModel, title="Hooks"
)


DEFAULT_VALUES = {
"hooks": {
"InstallAyonExtensionToPremiere": {
"enabled": False,
}
}
}

0 comments on commit bae8ed6

Please sign in to comment.