Applications: Use prelaunch hooks to extract environments (#5387)

* ApplicationManager can have more granular way how applications are launched

* executable is optional to be able create ApplicationLaunchContext

* launch context can run prelaunch hooks without launching application

* 'get_app_environments_for_context' is using launch context to prepare environments

* added 'launch_type' as one of filtering options for LaunchHook

* added 'local' launch type filter to existing launch hooks

* define 'automated' launch type in remote publish function

* modified publish and extract environments cli commands

* launch types are only for local by default

* fix import

* fix launch types of global host data

* change order or kwargs

* change unreal filter attribute
This commit is contained in:
Jakub Trllo 2023-08-03 10:04:15 +02:00 committed by GitHub
parent 55aead8470
commit 7e9f42b447
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 266 additions and 152 deletions

View file

@ -1,6 +1,6 @@
import os
from openpype.lib import PreLaunchHook
from openpype.lib.applications import PreLaunchHook, LaunchTypes
class AddLastWorkfileToLaunchArgs(PreLaunchHook):
@ -28,6 +28,7 @@ class AddLastWorkfileToLaunchArgs(PreLaunchHook):
"substancepainter",
"aftereffects"
]
launch_types = {LaunchTypes.local}
def execute(self):
if not self.data.get("start_last_workfile"):

View file

@ -1,7 +1,7 @@
import os
import shutil
from openpype.lib import PreLaunchHook
from openpype.settings import get_project_settings
from openpype.lib.applications import PreLaunchHook, LaunchTypes
from openpype.pipeline.workfile import (
get_custom_workfile_template,
get_custom_workfile_template_by_string_context
@ -20,6 +20,7 @@ class CopyTemplateWorkfile(PreLaunchHook):
# Before `AddLastWorkfileToLaunchArgs`
order = 0
app_groups = ["blender", "photoshop", "tvpaint", "aftereffects"]
launch_types = {LaunchTypes.local}
def execute(self):
"""Check if can copy template for context and do it if possible.

View file

@ -1,5 +1,5 @@
import os
from openpype.lib import PreLaunchHook
from openpype.lib.applications import PreLaunchHook, LaunchTypes
from openpype.pipeline.workfile import create_workdir_extra_folders
@ -14,6 +14,7 @@ class CreateWorkdirExtraFolders(PreLaunchHook):
# Execute after workfile template copy
order = 15
launch_types = {LaunchTypes.local}
def execute(self):
if not self.application.is_host:

View file

@ -1,5 +1,5 @@
import subprocess
from openpype.lib import PreLaunchHook
from openpype.lib.applications import PreLaunchHook, LaunchTypes
class LaunchFoundryAppsWindows(PreLaunchHook):
@ -15,6 +15,7 @@ class LaunchFoundryAppsWindows(PreLaunchHook):
order = 1000
app_groups = ["nuke", "nukeassist", "nukex", "hiero", "nukestudio"]
platforms = ["windows"]
launch_types = {LaunchTypes.local}
def execute(self):
# Change `creationflags` to CREATE_NEW_CONSOLE

View file

@ -1,5 +1,5 @@
from openpype.client import get_project, get_asset_by_name
from openpype.lib import (
from openpype.lib.applications import (
PreLaunchHook,
EnvironmentPrepData,
prepare_app_environments,
@ -10,6 +10,7 @@ from openpype.pipeline import Anatomy
class GlobalHostDataHook(PreLaunchHook):
order = -100
launch_types = set()
def execute(self):
"""Prepare global objects to `data` that will be used for sure."""

View file

@ -1,5 +1,5 @@
import os
from openpype.lib import PreLaunchHook
from openpype.lib.applications import PreLaunchHook, LaunchTypes
class LaunchWithTerminal(PreLaunchHook):
@ -13,6 +13,7 @@ class LaunchWithTerminal(PreLaunchHook):
order = 1000
platforms = ["darwin"]
launch_types = {LaunchTypes.local}
def execute(self):
executable = str(self.launch_context.executable)

View file

@ -1,10 +1,11 @@
import os
from openpype.lib import (
from openpype.lib import get_openpype_execute_args
from openpype.lib.applications import (
get_non_python_host_kwargs,
PreLaunchHook,
get_openpype_execute_args
LaunchTypes,
)
from openpype.lib.applications import get_non_python_host_kwargs
from openpype import PACKAGE_DIR as OPENPYPE_DIR
@ -19,6 +20,7 @@ class NonPythonHostHook(PreLaunchHook):
app_groups = ["harmony", "photoshop", "aftereffects"]
order = 20
launch_types = {LaunchTypes.local}
def execute(self):
# Pop executable
@ -54,4 +56,3 @@ class NonPythonHostHook(PreLaunchHook):
self.launch_context.kwargs = \
get_non_python_host_kwargs(self.launch_context.kwargs)

View file

@ -22,6 +22,7 @@ class OCIOEnvHook(PreLaunchHook):
"hiero",
"resolve"
]
launch_types = set()
def execute(self):
"""Hook entry method."""

View file

@ -1,6 +1,6 @@
from pathlib import Path
from openpype.lib import PreLaunchHook
from openpype.lib.applications import PreLaunchHook, LaunchTypes
class AddPythonScriptToLaunchArgs(PreLaunchHook):
@ -8,9 +8,8 @@ class AddPythonScriptToLaunchArgs(PreLaunchHook):
# Append after file argument
order = 15
app_groups = [
"blender",
]
app_groups = {"blender"}
launch_types = {LaunchTypes.local}
def execute(self):
if not self.launch_context.data.get("python_scripts"):

View file

@ -2,7 +2,7 @@ import os
import re
import subprocess
from platform import system
from openpype.lib import PreLaunchHook
from openpype.lib.applications import PreLaunchHook, LaunchTypes
class InstallPySideToBlender(PreLaunchHook):
@ -16,7 +16,8 @@ class InstallPySideToBlender(PreLaunchHook):
blender's python packages.
"""
app_groups = ["blender"]
app_groups = {"blender"}
launch_types = {LaunchTypes.local}
def execute(self):
# Prelaunch hook is not crucial

View file

@ -1,5 +1,5 @@
import subprocess
from openpype.lib import PreLaunchHook
from openpype.lib.applications import PreLaunchHook, LaunchTypes
class BlenderConsoleWindows(PreLaunchHook):
@ -15,6 +15,7 @@ class BlenderConsoleWindows(PreLaunchHook):
order = 1000
app_groups = ["blender"]
platforms = ["windows"]
launch_types = {LaunchTypes.local}
def execute(self):
# Change `creationflags` to CREATE_NEW_CONSOLE

View file

@ -2,7 +2,8 @@ import os
import shutil
import winreg
import subprocess
from openpype.lib import PreLaunchHook, get_openpype_execute_args
from openpype.lib import get_openpype_execute_args
from openpype.lib.applications import PreLaunchHook, LaunchTypes
from openpype.hosts.celaction import scripts
CELACTION_SCRIPTS_DIR = os.path.dirname(
@ -16,6 +17,7 @@ class CelactionPrelaunchHook(PreLaunchHook):
"""
app_groups = ["celaction"]
platforms = ["windows"]
launch_types = {LaunchTypes.local}
def execute(self):
asset_doc = self.data["asset_doc"]

View file

@ -6,13 +6,10 @@ import socket
from pprint import pformat
from openpype.lib import (
PreLaunchHook,
get_openpype_username,
run_subprocess,
)
from openpype.lib.applications import (
ApplicationLaunchFailed
)
from openpype.lib.applications import PreLaunchHook, LaunchTypes
from openpype.hosts import flame as opflame
@ -27,6 +24,7 @@ class FlamePrelaunch(PreLaunchHook):
wtc_script_path = os.path.join(
opflame.HOST_DIR, "api", "scripts", "wiretap_com.py")
launch_types = {LaunchTypes.local}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

View file

@ -2,12 +2,16 @@ import os
import shutil
import platform
from pathlib import Path
from openpype.lib import PreLaunchHook, ApplicationLaunchFailed
from openpype.hosts.fusion import (
FUSION_HOST_DIR,
FUSION_VERSIONS_DICT,
get_fusion_version,
)
from openpype.lib.applications import (
PreLaunchHook,
LaunchTypes,
ApplicationLaunchFailed,
)
class FusionCopyPrefsPrelaunch(PreLaunchHook):
@ -23,6 +27,7 @@ class FusionCopyPrefsPrelaunch(PreLaunchHook):
app_groups = ["fusion"]
order = 2
launch_types = {LaunchTypes.local}
def get_fusion_profile_name(self, profile_version) -> str:
# Returns 'Default', unless FUSION16_PROFILE is set

View file

@ -1,5 +1,9 @@
import os
from openpype.lib import PreLaunchHook, ApplicationLaunchFailed
from openpype.lib.applications import (
PreLaunchHook,
LaunchTypes,
ApplicationLaunchFailed,
)
from openpype.hosts.fusion import (
FUSION_HOST_DIR,
FUSION_VERSIONS_DICT,
@ -19,6 +23,7 @@ class FusionPrelaunch(PreLaunchHook):
app_groups = ["fusion"]
order = 1
launch_types = {LaunchTypes.local}
def execute(self):
# making sure python 3 is installed at provided path

View file

@ -1,4 +1,4 @@
from openpype.lib import PreLaunchHook
from openpype.lib.applications import PreLaunchHook, LaunchTypes
class SetPath(PreLaunchHook):
@ -7,6 +7,7 @@ class SetPath(PreLaunchHook):
Hook `GlobalHostDataHook` must be executed before this hook.
"""
app_groups = ["houdini"]
launch_types = {LaunchTypes.local}
def execute(self):
workdir = self.launch_context.env.get("AVALON_WORKDIR", "")

View file

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
"""Pre-launch to force 3ds max startup script."""
from openpype.lib import PreLaunchHook
import os
from openpype.lib.applications import PreLaunchHook, LaunchTypes
class ForceStartupScript(PreLaunchHook):
@ -15,6 +15,7 @@ class ForceStartupScript(PreLaunchHook):
"""
app_groups = ["3dsmax"]
order = 11
launch_types = {LaunchTypes.local}
def execute(self):
startup_args = [

View file

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
"""Pre-launch hook to inject python environment."""
from openpype.lib import PreLaunchHook
import os
from openpype.lib.applications import PreLaunchHook, LaunchTypes
class InjectPythonPath(PreLaunchHook):
@ -14,6 +14,7 @@ class InjectPythonPath(PreLaunchHook):
Hook `GlobalHostDataHook` must be executed before this hook.
"""
app_groups = ["3dsmax"]
launch_types = {LaunchTypes.local}
def execute(self):
self.launch_context.env["MAX_PYTHONPATH"] = os.environ["PYTHONPATH"]

View file

@ -1,4 +1,4 @@
from openpype.lib import PreLaunchHook
from openpype.lib.applications import PreLaunchHook, LaunchTypes
class SetPath(PreLaunchHook):
@ -7,6 +7,7 @@ class SetPath(PreLaunchHook):
Hook `GlobalHostDataHook` must be executed before this hook.
"""
app_groups = ["max"]
launch_types = {LaunchTypes.local}
def execute(self):
workdir = self.launch_context.env.get("AVALON_WORKDIR", "")

View file

@ -1,4 +1,4 @@
from openpype.lib import PreLaunchHook
from openpype.lib.applications import PreLaunchHook, LaunchTypes
class MayaPreAutoLoadPlugins(PreLaunchHook):
@ -7,6 +7,7 @@ class MayaPreAutoLoadPlugins(PreLaunchHook):
# Before AddLastWorkfileToLaunchArgs
order = 9
app_groups = ["maya"]
launch_types = {LaunchTypes.local}
def execute(self):

View file

@ -1,4 +1,4 @@
from openpype.lib import PreLaunchHook
from openpype.lib.applications import PreLaunchHook, LaunchTypes
from openpype.hosts.maya.lib import create_workspace_mel
@ -8,6 +8,7 @@ class PreCopyMel(PreLaunchHook):
Hook `GlobalHostDataHook` must be executed before this hook.
"""
app_groups = ["maya"]
launch_types = {LaunchTypes.local}
def execute(self):
project_doc = self.data["project_doc"]

View file

@ -1,4 +1,4 @@
from openpype.lib import PreLaunchHook
from openpype.lib.applications import PreLaunchHook, LaunchTypes
class MayaPreOpenWorkfilePostInitialization(PreLaunchHook):
@ -7,6 +7,7 @@ class MayaPreOpenWorkfilePostInitialization(PreLaunchHook):
# Before AddLastWorkfileToLaunchArgs.
order = 9
app_groups = ["maya"]
launch_types = {LaunchTypes.local}
def execute(self):

View file

@ -1,4 +1,4 @@
from openpype.lib import PreLaunchHook
from openpype.lib.applications import PreLaunchHook
class PrelaunchNukeAssistHook(PreLaunchHook):
@ -6,6 +6,7 @@ class PrelaunchNukeAssistHook(PreLaunchHook):
Adding flag when nukeassist
"""
app_groups = ["nukeassist"]
launch_types = set()
def execute(self):
self.launch_context.env["NUKEASSIST"] = "1"

View file

@ -1,5 +1,5 @@
import os
from openpype.lib import PreLaunchHook
from openpype.lib.applications import PreLaunchHook, LaunchTypes
class PreLaunchResolveLastWorkfile(PreLaunchHook):
@ -10,6 +10,7 @@ class PreLaunchResolveLastWorkfile(PreLaunchHook):
"""
order = 10
app_groups = ["resolve"]
launch_types = {LaunchTypes.local}
def execute(self):
if not self.data.get("start_last_workfile"):

View file

@ -1,7 +1,7 @@
import os
from pathlib import Path
import platform
from openpype.lib import PreLaunchHook
from openpype.lib.applications import PreLaunchHook, LaunchTypes
from openpype.hosts.resolve.utils import setup
@ -31,6 +31,7 @@ class PreLaunchResolveSetup(PreLaunchHook):
"""
app_groups = ["resolve"]
launch_types = {LaunchTypes.local}
def execute(self):
current_platform = platform.system().lower()

View file

@ -1,6 +1,6 @@
import os
from openpype.lib import PreLaunchHook
from openpype.lib.applications import PreLaunchHook, LaunchTypes
import openpype.hosts.resolve
@ -10,6 +10,7 @@ class PreLaunchResolveStartup(PreLaunchHook):
"""
order = 11
app_groups = ["resolve"]
launch_types = {LaunchTypes.local}
def execute(self):
# Set the openpype prelaunch startup script path for easy access

View file

@ -1,7 +1,5 @@
from openpype.lib import (
PreLaunchHook,
get_openpype_execute_args
)
from openpype.lib import get_openpype_execute_args
from openpype.lib.applications import PreLaunchHook, LaunchTypes
class TvpaintPrelaunchHook(PreLaunchHook):
@ -14,6 +12,7 @@ class TvpaintPrelaunchHook(PreLaunchHook):
to copy templated workfile from predefined path.
"""
app_groups = ["tvpaint"]
launch_types = {LaunchTypes.local}
def execute(self):
# Pop tvpaint executable

View file

@ -7,9 +7,10 @@ from pathlib import Path
from qtpy import QtCore
from openpype import resources
from openpype.lib import (
from openpype.lib.applications import (
PreLaunchHook,
ApplicationLaunchFailed,
LaunchTypes,
)
from openpype.pipeline.workfile import get_workfile_template_key
import openpype.hosts.unreal.lib as unreal_lib
@ -29,6 +30,8 @@ class UnrealPrelaunchHook(PreLaunchHook):
shell script.
"""
app_groups = {"unreal"}
launch_types = {LaunchTypes.local}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

View file

@ -6,7 +6,7 @@ import pyblish.util
from openpype.lib import Logger
from openpype.lib.applications import (
ApplicationManager,
get_app_environments_for_context,
LaunchTypes,
)
from openpype.pipeline import install_host
from openpype.hosts.webpublisher.api import WebpublisherHost
@ -156,22 +156,31 @@ def cli_publish_from_app(
found_variant_key = find_variant_key(application_manager, host_name)
app_name = "{}/{}".format(host_name, found_variant_key)
data = {
"last_workfile_path": workfile_path,
"start_last_workfile": True,
"project_name": project_name,
"asset_name": asset_name,
"task_name": task_name,
"launch_type": LaunchTypes.automated,
}
launch_context = application_manager.create_launch_context(
app_name, **data)
launch_context.run_prelaunch_hooks()
# must have for proper launch of app
env = get_app_environments_for_context(
project_name,
asset_name,
task_name,
app_name
)
env = launch_context.env
print("env:: {}".format(env))
env["OPENPYPE_PUBLISH_DATA"] = batch_path
# must pass identifier to update log lines for a batch
env["BATCH_LOG_ID"] = str(_id)
env["HEADLESS_PUBLISH"] = 'true' # to use in app lib
env["USER_EMAIL"] = user_email
os.environ.update(env)
os.environ["OPENPYPE_PUBLISH_DATA"] = batch_path
# must pass identifier to update log lines for a batch
os.environ["BATCH_LOG_ID"] = str(_id)
os.environ["HEADLESS_PUBLISH"] = 'true' # to use in app lib
os.environ["USER_EMAIL"] = user_email
# Why is this here? Registered host in this process does not affect
# regitered host in launched process.
pyblish.api.register_host(host_name)
if targets:
if isinstance(targets, str):
@ -184,15 +193,7 @@ def cli_publish_from_app(
os.environ["PYBLISH_TARGETS"] = os.pathsep.join(
set(current_targets))
data = {
"last_workfile_path": workfile_path,
"start_last_workfile": True,
"project_name": project_name,
"asset_name": asset_name,
"task_name": task_name
}
launched_app = application_manager.launch(app_name, **data)
launched_app = application_manager.launch_with_context(launch_context)
timeout = get_timeout(project_name, host_name, task_type)

View file

@ -12,10 +12,6 @@ from abc import ABCMeta, abstractmethod
import six
from openpype import AYON_SERVER_ENABLED, PACKAGE_DIR
from openpype.client import (
get_project,
get_asset_by_name,
)
from openpype.settings import (
get_system_settings,
get_project_settings,
@ -47,6 +43,25 @@ CUSTOM_LAUNCH_APP_GROUPS = {
}
class LaunchTypes:
"""Launch types are filters for pre/post-launch hooks.
Please use these variables in case they'll change values.
"""
# Local launch - application is launched on local machine
local = "local"
# Farm render job - application is on farm
farm_render = "farm-render"
# Farm publish job - integration post-render job
farm_publish = "farm-publish"
# Remote launch - application is launched on remote machine from which
# can be started publishing
remote = "remote"
# Automated launch - application is launched with automated publishing
automated = "automated"
def parse_environments(env_data, env_group=None, platform_name=None):
"""Parse environment values from settings byt group and platform.
@ -483,6 +498,42 @@ class ApplicationManager:
break
return output
def create_launch_context(self, app_name, **data):
"""Prepare launch context for application.
Args:
app_name (str): Name of application that should be launched.
**data (Any): Any additional data. Data may be used during
Returns:
ApplicationLaunchContext: Launch context for application.
Raises:
ApplicationNotFound: Application was not found by entered name.
"""
app = self.applications.get(app_name)
if not app:
raise ApplicationNotFound(app_name)
executable = app.find_executable()
return ApplicationLaunchContext(
app, executable, **data
)
def launch_with_context(self, launch_context):
"""Launch application using existing launch context.
Args:
launch_context (ApplicationLaunchContext): Prepared launch
context.
"""
if not launch_context.executable:
raise ApplictionExecutableNotFound(launch_context.application)
return launch_context.launch()
def launch(self, app_name, **data):
"""Launch procedure.
@ -503,18 +554,10 @@ class ApplicationManager:
failed. Exception should contain explanation message,
traceback should not be needed.
"""
app = self.applications.get(app_name)
if not app:
raise ApplicationNotFound(app_name)
executable = app.find_executable()
if not executable:
raise ApplictionExecutableNotFound(app)
context = self.create_launch_context(app_name, **data)
return self.launch_with_context(context)
context = ApplicationLaunchContext(
app, executable, **data
)
return context.launch()
class EnvironmentToolGroup:
@ -736,13 +779,17 @@ class LaunchHook:
# Order of prelaunch hook, will be executed as last if set to None.
order = None
# List of host implementations, skipped if empty.
hosts = []
# List of application groups
app_groups = []
# List of specific application names
app_names = []
# List of platform availability, skipped if empty.
platforms = []
hosts = set()
# Set of application groups
app_groups = set()
# Set of specific application names
app_names = set()
# Set of platform availability
platforms = set()
# Set of launch types for which is available
# - if empty then is available for all launch types
# - by default has 'local' which is most common reason for launc hooks
launch_types = {LaunchTypes.local}
def __init__(self, launch_context):
"""Constructor of launch hook.
@ -790,6 +837,10 @@ class LaunchHook:
if launch_context.app_name not in cls.app_names:
return False
if cls.launch_types:
if launch_context.launch_type not in cls.launch_types:
return False
return True
@property
@ -859,9 +910,9 @@ class PostLaunchHook(LaunchHook):
class ApplicationLaunchContext:
"""Context of launching application.
Main purpose of context is to prepare launch arguments and keyword arguments
for new process. Most important part of keyword arguments preparations
are environment variables.
Main purpose of context is to prepare launch arguments and keyword
arguments for new process. Most important part of keyword arguments
preparations are environment variables.
During the whole process is possible to use `data` attribute to store
object usable in multiple places.
@ -874,14 +925,30 @@ class ApplicationLaunchContext:
insert argument between `nuke.exe` and `--NukeX`. To keep them together
it is better to wrap them in another list: `[["nuke.exe", "--NukeX"]]`.
Notes:
It is possible to use launch context only to prepare environment
variables. In that case `executable` may be None and can be used
'run_prelaunch_hooks' method to run prelaunch hooks which prepare
them.
Args:
application (Application): Application definition.
executable (ApplicationExecutable): Object with path to executable.
env_group (Optional[str]): Environment variable group. If not set
'DEFAULT_ENV_SUBGROUP' is used.
launch_type (Optional[str]): Launch type. If not set 'local' is used.
**data (dict): Any additional data. Data may be used during
preparation to store objects usable in multiple places.
"""
def __init__(self, application, executable, env_group=None, **data):
def __init__(
self,
application,
executable,
env_group=None,
launch_type=None,
**data
):
from openpype.modules import ModulesManager
# Application object
@ -896,6 +963,10 @@ class ApplicationLaunchContext:
self.executable = executable
if launch_type is None:
launch_type = LaunchTypes.local
self.launch_type = launch_type
if env_group is None:
env_group = DEFAULT_ENV_SUBGROUP
@ -903,8 +974,11 @@ class ApplicationLaunchContext:
self.data = dict(data)
launch_args = []
if executable is not None:
launch_args = executable.as_args()
# subprocess.Popen launch arguments (first argument in constructor)
self.launch_args = executable.as_args()
self.launch_args = launch_args
self.launch_args.extend(application.arguments)
if self.data.get("app_args"):
self.launch_args.extend(self.data.pop("app_args"))
@ -946,6 +1020,7 @@ class ApplicationLaunchContext:
self.postlaunch_hooks = None
self.process = None
self._prelaunch_hooks_executed = False
@property
def env(self):
@ -1215,6 +1290,27 @@ class ApplicationLaunchContext:
# Return process which is already terminated
return process
def run_prelaunch_hooks(self):
"""Run prelaunch hooks.
This method will be executed only once, any future calls will skip
the processing.
"""
if self._prelaunch_hooks_executed:
self.log.warning("Prelaunch hooks were already executed.")
return
# Discover launch hooks
self.discover_launch_hooks()
# Execute prelaunch hooks
for prelaunch_hook in self.prelaunch_hooks:
self.log.debug("Executing prelaunch hook: {}".format(
str(prelaunch_hook.__class__.__name__)
))
prelaunch_hook.execute()
self._prelaunch_hooks_executed = True
def launch(self):
"""Collect data for new process and then create it.
@ -1227,15 +1323,8 @@ class ApplicationLaunchContext:
self.log.warning("Application was already launched.")
return
# Discover launch hooks
self.discover_launch_hooks()
# Execute prelaunch hooks
for prelaunch_hook in self.prelaunch_hooks:
self.log.debug("Executing prelaunch hook: {}".format(
str(prelaunch_hook.__class__.__name__)
))
prelaunch_hook.execute()
if not self._prelaunch_hooks_executed:
self.run_prelaunch_hooks()
self.log.debug("All prelaunch hook executed. Starting new process.")
@ -1353,6 +1442,7 @@ def get_app_environments_for_context(
task_name,
app_name,
env_group=None,
launch_type=None,
env=None,
modules_manager=None
):
@ -1363,54 +1453,33 @@ def get_app_environments_for_context(
task_name (str): Name of task.
app_name (str): Name of application that is launched and can be found
by ApplicationManager.
env (dict): Initial environment variables. `os.environ` is used when
not passed.
modules_manager (ModulesManager): Initialized modules manager.
env_group (Optional[str]): Name of environment group. If not passed
default group is used.
launch_type (Optional[str]): Type for which prelaunch hooks are
executed.
env (Optional[dict[str, str]]): Initial environment variables.
`os.environ` is used when not passed.
modules_manager (Optional[ModulesManager]): Initialized modules
manager.
Returns:
dict: Environments for passed context and application.
"""
from openpype.modules import ModulesManager
from openpype.pipeline import Anatomy
from openpype.lib.openpype_version import is_running_staging
# Project document
project_doc = get_project(project_name)
asset_doc = get_asset_by_name(project_name, asset_name)
if modules_manager is None:
modules_manager = ModulesManager()
# Prepare app object which can be obtained only from ApplciationManager
# Prepare app object which can be obtained only from ApplicationManager
app_manager = ApplicationManager()
app = app_manager.applications[app_name]
# Project's anatomy
anatomy = Anatomy(project_name)
data = EnvironmentPrepData({
"project_name": project_name,
"asset_name": asset_name,
"task_name": task_name,
"app": app,
"project_doc": project_doc,
"asset_doc": asset_doc,
"anatomy": anatomy,
"env": env
})
data["env"].update(anatomy.root_environments())
if is_running_staging():
data["env"]["OPENPYPE_IS_STAGING"] = "1"
prepare_app_environments(data, env_group, modules_manager)
prepare_context_environments(data, env_group, modules_manager)
return data["env"]
context = app_manager.create_launch_context(
app_name,
project_name=project_name,
asset_name=asset_name,
task_name=task_name,
env_group=env_group,
launch_type=launch_type,
env=env,
modules_manager=modules_manager,
)
context.run_prelaunch_hooks()
return context.env
def _merge_env(env, current_env):

View file

@ -2,11 +2,12 @@ import os
import ftrack_api
from openpype.settings import get_project_settings
from openpype.lib import PostLaunchHook
from openpype.lib.applications import PostLaunchHook, LaunchTypes
class PostFtrackHook(PostLaunchHook):
order = None
launch_types = {LaunchTypes.local}
def execute(self):
project_name = self.data.get("project_name")

View file

@ -1,5 +1,5 @@
import os
from openpype.lib import PreLaunchHook
from openpype.lib.applications import PreLaunchHook
from openpype_modules.slack import SLACK_MODULE_DIR
@ -8,6 +8,7 @@ class PrePython2Support(PreLaunchHook):
Path to vendor modules is added to the beginning of PYTHONPATH.
"""
launch_types = set()
def execute(self):
if not self.application.use_python_2:

View file

@ -1,12 +1,8 @@
import os
import shutil
from openpype.client.entities import (
get_representations,
get_project
)
from openpype.lib import PreLaunchHook
from openpype.client.entities import get_representations
from openpype.lib.applications import PreLaunchHook, LaunchTypes
from openpype.lib.profiles_filtering import filter_profiles
from openpype.modules.sync_server.sync_server import (
download_last_published_workfile,
@ -32,6 +28,7 @@ class CopyLastPublishedWorkfile(PreLaunchHook):
"nuke", "nukeassist", "nukex", "hiero", "nukestudio",
"maya", "harmony", "celaction", "flame", "fusion",
"houdini", "tvpaint"]
launch_types = {LaunchTypes.local}
def execute(self):
"""Check if local workfile doesn't exist, else copy it.

View file

@ -1,4 +1,4 @@
from openpype.lib import PostLaunchHook
from openpype.lib.applications import PostLaunchHook, LaunchTypes
class PostStartTimerHook(PostLaunchHook):
@ -7,6 +7,7 @@ class PostStartTimerHook(PostLaunchHook):
This module requires enabled TimerManager module.
"""
order = None
launch_types = {LaunchTypes.local}
def execute(self):
project_name = self.data.get("project_name")

View file

@ -88,7 +88,10 @@ class PypeCommands:
"""
from openpype.lib import Logger
from openpype.lib.applications import get_app_environments_for_context
from openpype.lib.applications import (
get_app_environments_for_context,
LaunchTypes,
)
from openpype.modules import ModulesManager
from openpype.pipeline import (
install_openpype_plugins,
@ -122,7 +125,8 @@ class PypeCommands:
context["project_name"],
context["asset_name"],
context["task_name"],
app_full_name
app_full_name,
launch_type=LaunchTypes.farm_publish,
)
os.environ.update(env)
@ -237,11 +241,19 @@ class PypeCommands:
Called by Deadline plugin to propagate environment into render jobs.
"""
from openpype.lib.applications import get_app_environments_for_context
from openpype.lib.applications import (
get_app_environments_for_context,
LaunchTypes,
)
if all((project, asset, task, app)):
env = get_app_environments_for_context(
project, asset, task, app, env_group
project,
asset,
task,
app,
env_group=env_group,
launch_type=LaunchTypes.farm_render,
)
else:
env = os.environ.copy()