Skip to content
This repository has been archived by the owner on Sep 20, 2024. It is now read-only.

General: Local overrides for environment variables #3045

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 36 additions & 5 deletions openpype/lib/applications.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@

from openpype.settings import (
get_system_settings,
get_project_settings
get_project_settings,
get_local_settings
)
from openpype.settings.constants import (
METADATA_KEYS,
Expand Down Expand Up @@ -1272,6 +1273,9 @@ def __init__(self, data):
if data.get("env") is None:
data["env"] = os.environ.copy()

if "system_settings" not in data:
data["system_settings"] = get_system_settings()

super(EnvironmentPrepData, self).__init__(data)


Expand Down Expand Up @@ -1395,8 +1399,27 @@ def prepare_app_environments(data, env_group=None, implementation_envs=True):

app = data["app"]
log = data["log"]
source_env = data["env"].copy()

_add_python_version_paths(app, source_env, log)

# Use environments from local settings
filtered_local_envs = {}
system_settings = data["system_settings"]
whitelist_envs = system_settings["general"].get("local_env_white_list")
if whitelist_envs:
local_settings = get_local_settings()
local_envs = local_settings.get("environments") or {}
filtered_local_envs = {
key: value
for key, value in local_envs.items()
if key in whitelist_envs
}

_add_python_version_paths(app, data["env"], log)
# Apply local environment variables for already existing values
for key, value in filtered_local_envs.items():
if key in source_env:
source_env[key] = value

# `added_env_keys` has debug purpose
added_env_keys = {app.group.name, app.name}
Expand Down Expand Up @@ -1441,10 +1464,19 @@ def prepare_app_environments(data, env_group=None, implementation_envs=True):

# Choose right platform
tool_env = parse_environments(_env_values, env_group)

# Apply local environment variables
# - must happen between all values because they may be used during
# merge
for key, value in filtered_local_envs.items():
if key in tool_env:
tool_env[key] = value

# Merge dictionaries
env_values = _merge_env(tool_env, env_values)

merged_env = _merge_env(env_values, data["env"])
merged_env = _merge_env(env_values, source_env)

loaded_env = acre.compute(merged_env, cleanup=False)

final_env = None
Expand All @@ -1464,7 +1496,7 @@ def prepare_app_environments(data, env_group=None, implementation_envs=True):
if final_env is None:
final_env = loaded_env

keys_to_remove = set(data["env"].keys()) - set(final_env.keys())
keys_to_remove = set(source_env.keys()) - set(final_env.keys())

# Update env
data["env"].update(final_env)
Expand Down Expand Up @@ -1611,7 +1643,6 @@ def _prepare_last_workfile(data, workdir):
result will be stored.
workdir (str): Path to folder where workfiles should be stored.
"""
import avalon.api
from openpype.pipeline import HOST_WORKFILE_EXTENSIONS

log = data["log"]
Expand Down
1 change: 1 addition & 0 deletions openpype/settings/defaults/system_settings/general.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"linux": [],
"darwin": []
},
"local_env_white_list": [],
"openpype_path": {
"windows": [],
"darwin": [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,17 @@
{
"type": "splitter"
},
{
"type": "list",
"key": "local_env_white_list",
"label": "Local overrides of environment variable keys",
"tooltip": "Environment variable keys that can be changed per machine using Local settings UI.\nKey changes are applied only on applications and tools environments.",
"use_label_wrap": true,
"object_type": "text"
},
{
"type": "splitter"
},
{
"type": "collapsible-wrap",
"label": "OpenPype deployment control",
Expand Down
8 changes: 8 additions & 0 deletions openpype/settings/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -1113,6 +1113,14 @@ def get_general_environments():

clear_metadata_from_settings(environments)

whitelist_envs = result["general"].get("local_env_white_list")
if whitelist_envs:
local_settings = get_local_settings()
local_envs = local_settings.get("environments") or {}
for key, value in local_envs.items():
if key in whitelist_envs and key in environments:
environments[key] = value

return environments


Expand Down
1 change: 1 addition & 0 deletions openpype/tools/settings/local_settings/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
# TODO move to settings constants
LOCAL_GENERAL_KEY = "general"
LOCAL_PROJECTS_KEY = "projects"
LOCAL_ENV_KEY = "environments"
LOCAL_APPS_KEY = "applications"

# Roots key constant
Expand Down
93 changes: 93 additions & 0 deletions openpype/tools/settings/local_settings/environments_widget.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
from Qt import QtWidgets

from openpype.tools.utils import PlaceholderLineEdit


class LocalEnvironmentsWidgets(QtWidgets.QWidget):
def __init__(self, system_settings_entity, parent):
super(LocalEnvironmentsWidgets, self).__init__(parent)

self._widgets_by_env_key = {}
self.system_settings_entity = system_settings_entity

content_widget = QtWidgets.QWidget(self)
content_layout = QtWidgets.QGridLayout(content_widget)
content_layout.setContentsMargins(0, 0, 0, 0)

layout = QtWidgets.QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)

self._layout = layout
self._content_layout = content_layout
self._content_widget = content_widget

def _clear_layout(self, layout):
while layout.count() > 0:
item = layout.itemAt(0)
widget = item.widget()
layout.removeItem(item)
if widget is not None:
widget.setVisible(False)
widget.deleteLater()

def _reset_env_widgets(self):
self._clear_layout(self._content_layout)
self._clear_layout(self._layout)

content_widget = QtWidgets.QWidget(self)
content_layout = QtWidgets.QGridLayout(content_widget)
content_layout.setContentsMargins(0, 0, 0, 0)
white_list_entity = (
self.system_settings_entity["general"]["local_env_white_list"]
)
row = -1
for row, item in enumerate(white_list_entity):
key = item.value
label_widget = QtWidgets.QLabel(key, self)
input_widget = PlaceholderLineEdit(self)
input_widget.setPlaceholderText("< Keep studio value >")

content_layout.addWidget(label_widget, row, 0)
content_layout.addWidget(input_widget, row, 1)

self._widgets_by_env_key[key] = input_widget

if row < 0:
label_widget = QtWidgets.QLabel(
(
"Your studio does not allow to change"
" Environment variables locally."
),
self
)
content_layout.addWidget(label_widget, 0, 0)
content_layout.setColumnStretch(0, 1)

else:
content_layout.setColumnStretch(0, 0)
content_layout.setColumnStretch(1, 1)

self._layout.addWidget(content_widget, 1)

self._content_layout = content_layout
self._content_widget = content_widget

def update_local_settings(self, value):
if not value:
value = {}

self._reset_env_widgets()

for env_key, widget in self._widgets_by_env_key.items():
env_value = value.get(env_key) or ""
widget.setText(env_value)

def settings_value(self):
output = {}
for env_key, widget in self._widgets_by_env_key.items():
value = widget.text()
if value:
output[env_key] = value
if not output:
return None
return output
31 changes: 29 additions & 2 deletions openpype/tools/settings/local_settings/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@
LOCAL_EXPERIMENTAL_KEY
)
from .apps_widget import LocalApplicationsWidgets
from .environments_widget import LocalEnvironmentsWidgets
from .projects_widget import ProjectSettingsWidget

from .constants import (
LOCAL_GENERAL_KEY,
LOCAL_PROJECTS_KEY,
LOCAL_ENV_KEY,
LOCAL_APPS_KEY
)

Expand All @@ -49,18 +51,20 @@ def __init__(self, parent=None):
self.pype_mongo_widget = None
self.general_widget = None
self.experimental_widget = None
self.envs_widget = None
self.apps_widget = None
self.projects_widget = None

self._create_pype_mongo_ui()
self._create_mongo_url_ui()
self._create_general_ui()
self._create_experimental_ui()
self._create_environments_ui()
self._create_app_ui()
self._create_project_ui()

self.main_layout.addStretch(1)

def _create_pype_mongo_ui(self):
def _create_mongo_url_ui(self):
pype_mongo_expand_widget = ExpandingWidget("OpenPype Mongo URL", self)
pype_mongo_content = QtWidgets.QWidget(self)
pype_mongo_layout = QtWidgets.QVBoxLayout(pype_mongo_content)
Expand Down Expand Up @@ -110,6 +114,22 @@ def _create_experimental_ui(self):

self.experimental_widget = experimental_widget

def _create_environments_ui(self):
envs_expand_widget = ExpandingWidget("Environments", self)
envs_content = QtWidgets.QWidget(self)
envs_layout = QtWidgets.QVBoxLayout(envs_content)
envs_layout.setContentsMargins(CHILD_OFFSET, 5, 0, 0)
envs_expand_widget.set_content_widget(envs_content)

envs_widget = LocalEnvironmentsWidgets(
self.system_settings, envs_content
)
envs_layout.addWidget(envs_widget)

self.main_layout.addWidget(envs_expand_widget)

self.envs_widget = envs_widget

def _create_app_ui(self):
# Applications
app_expand_widget = ExpandingWidget("Applications", self)
Expand Down Expand Up @@ -154,6 +174,9 @@ def update_local_settings(self, value):
self.general_widget.update_local_settings(
value.get(LOCAL_GENERAL_KEY)
)
self.envs_widget.update_local_settings(
value.get(LOCAL_ENV_KEY)
)
self.app_widget.update_local_settings(
value.get(LOCAL_APPS_KEY)
)
Expand All @@ -170,6 +193,10 @@ def settings_value(self):
if general_value:
output[LOCAL_GENERAL_KEY] = general_value

envs_value = self.envs_widget.settings_value()
if envs_value:
output[LOCAL_ENV_KEY] = envs_value

app_value = self.app_widget.settings_value()
if app_value:
output[LOCAL_APPS_KEY] = app_value
Expand Down