Bases: PreLaunchHook
Special hook to ensure installed version is compatible with AYON.
Source code in client/ayon_resolve/hooks/pre_resolve_check_version.py
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 | class PreLaunchResolveCheckVersion(PreLaunchHook):
"""Special hook to ensure installed version is compatible with AYON.
"""
order = 10
app_groups = {"resolve"}
launch_types = {LaunchTypes.local}
def _find_readme(self, executable: str) -> Path | None:
"""Locate the ReadMe.html shipped with the Resolve install.
- Windows: <install>/Resolve.exe -> <install>/Documents
- Linux: /opt/resolve/bin/resolve -> /opt/resolve/Documents
- macOS: .../Contents/MacOS/Resolve -> .../Contents/Documents
"""
exe = Path(executable).resolve()
for base in list(exe.parents)[:4]:
candidate = base / "Documents" / "ReadMe.html"
if candidate.is_file():
return candidate
return None
@staticmethod
def _parse_readme(readme: Path) -> tuple[str | None, bool]:
""" Return version + is studio from readme file.
"""
text = readme.read_text(encoding="utf-8", errors="replace")
version = None
match = re.search(
r"<title>\s*DaVinci Resolve\s+(\d+\.\d[\d.]*)",
text,
re.IGNORECASE,
)
if not match:
match = re.search(
r"\bDaVinci Resolve(?:\s+Studio)?\s+(\d+\.\d[\d.]*)", text
)
if match:
version = match.group(1).rstrip(".")
is_studio = bool(
re.search(r"About DaVinci Resolve\s+Studio\s+\d", text, re.IGNORECASE)
)
return version, is_studio
@staticmethod
def _is_supported(version: str | None, is_studio: bool) -> bool:
"""Free Resolve 21+ dropped external python scripting."""
if is_studio:
return True
if not version:
# Unknown version, do not block the launch.
return True
major = int(version.split(".")[0])
return major < 21
def _should_run_resolve_check_version(self) -> bool:
resolve_settings = self.data["project_settings"]["resolve"]
return resolve_settings["check_compatible_version_on_start"]
def execute(self):
if not self._should_run_resolve_check_version():
return
executable = self.launch_context.launch_args[0]
# Detect Resolve version from the shipped ReadMe
# Cannot rely on '-v' executable output, as it cannot be reliably captured.
readme = self._find_readme(executable)
if readme is None:
self.log.warning(
"Could not locate Resolve ReadMe.html "
"from executable: %s.",
executable,
)
return
try:
version, is_studio = self._parse_readme(readme)
except OSError:
self.log.warning(
"Could not gather version from ReadMe.html at %s. "
"Skipping compatibility check.",
readme,
exc_info=True,
)
return
edition = "Studio" if is_studio else "Free"
self.log.debug("Detected DaVinci Resolve %s %s", edition, version)
if not self._is_supported(version, is_studio):
raise ApplicationLaunchFailed(
f"AYON is not supported in DaVinci Resolve {edition} {version}. "
"Only the studio version supports python external scripting:\n"
"https://forum.blackmagicdesign.com/viewtopic.php?f=21&t=239823"
)
|