mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
extracted current storing process to SettingsFileHandler
This commit is contained in:
parent
5d9fb93558
commit
de92f0a8d3
3 changed files with 248 additions and 172 deletions
|
|
@ -1,5 +1,24 @@
|
|||
import os
|
||||
import json
|
||||
import logging
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import six
|
||||
import pype
|
||||
from .constants import (
|
||||
M_OVERRIDEN_KEY,
|
||||
M_ENVIRONMENT_KEY,
|
||||
M_DYNAMIC_KEY_LABEL,
|
||||
M_POP_KEY,
|
||||
|
||||
METADATA_KEYS,
|
||||
|
||||
SYSTEM_SETTINGS_KEY,
|
||||
ENVIRONMENTS_KEY,
|
||||
PROJECT_SETTINGS_KEY,
|
||||
PROJECT_ANATOMY_KEY
|
||||
)
|
||||
|
||||
JSON_EXC = getattr(json.decoder, "JSONDecodeError", ValueError)
|
||||
|
||||
|
||||
@six.add_metaclass(ABCMeta)
|
||||
|
|
@ -87,3 +106,192 @@ class SettingsHandler:
|
|||
"""
|
||||
pass
|
||||
|
||||
|
||||
class SettingsFileHandler(SettingsHandler):
|
||||
def __init__(self):
|
||||
self.log = logging.getLogger("SettingsFileHandler")
|
||||
|
||||
# Folder where studio overrides are stored
|
||||
studio_overrides_dir = os.getenv("PYPE_PROJECT_CONFIGS")
|
||||
if not studio_overrides_dir:
|
||||
studio_overrides_dir = os.path.dirname(os.path.dirname(
|
||||
os.path.abspath(pype.__file__)
|
||||
))
|
||||
system_settings_path = os.path.join(
|
||||
studio_overrides_dir, SYSTEM_SETTINGS_KEY + ".json"
|
||||
)
|
||||
|
||||
# File where studio's default project overrides are stored
|
||||
project_settings_filename = PROJECT_SETTINGS_KEY + ".json"
|
||||
project_settings_path = os.path.join(
|
||||
studio_overrides_dir, project_settings_filename
|
||||
)
|
||||
|
||||
project_anatomy_filename = PROJECT_ANATOMY_KEY + ".json"
|
||||
project_anatomy_path = os.path.join(
|
||||
studio_overrides_dir, project_anatomy_filename
|
||||
)
|
||||
|
||||
self.studio_overrides_dir = studio_overrides_dir
|
||||
self.system_settings_path = system_settings_path
|
||||
|
||||
self.project_settings_filename = project_settings_filename
|
||||
self.project_anatomy_filename = project_anatomy_filename
|
||||
|
||||
self.project_settings_path = project_settings_path
|
||||
self.project_anatomy_path = project_anatomy_path
|
||||
|
||||
def load_json_file(self, fpath):
|
||||
# Load json data
|
||||
try:
|
||||
with open(fpath, "r") as opened_file:
|
||||
return json.load(opened_file)
|
||||
|
||||
except JSON_EXC:
|
||||
self.log.warning(
|
||||
"File has invalid json format \"{}\"".format(fpath),
|
||||
exc_info=True
|
||||
)
|
||||
return {}
|
||||
|
||||
def path_to_project_settings(self, project_name):
|
||||
if not project_name:
|
||||
return self.project_settings_path
|
||||
return os.path.join(
|
||||
self.studio_overrides_dir,
|
||||
project_name,
|
||||
self.project_settings_filename
|
||||
)
|
||||
|
||||
def path_to_project_anatomy(self, project_name):
|
||||
if not project_name:
|
||||
return self.project_anatomy_path
|
||||
return os.path.join(
|
||||
self.studio_overrides_dir,
|
||||
project_name,
|
||||
self.project_anatomy_filename
|
||||
)
|
||||
|
||||
def save_studio_settings(self, data):
|
||||
"""Save studio overrides of system settings.
|
||||
|
||||
Do not use to store whole system settings data with defaults but only
|
||||
it's overrides with metadata defining how overrides should be applied
|
||||
in load function. For loading should be used function
|
||||
`studio_system_settings`.
|
||||
|
||||
Args:
|
||||
data(dict): Data of studio overrides with override metadata.
|
||||
"""
|
||||
dirpath = os.path.dirname(self.system_settings_path)
|
||||
if not os.path.exists(dirpath):
|
||||
os.makedirs(dirpath)
|
||||
|
||||
self.log.debug(
|
||||
"Saving studio overrides. Output path: {}".format(
|
||||
self.system_settings_path
|
||||
)
|
||||
)
|
||||
with open(self.system_settings_path, "w") as file_stream:
|
||||
json.dump(data, file_stream, indent=4)
|
||||
|
||||
def save_project_settings(self, project_name, overrides):
|
||||
"""Save studio overrides of project settings.
|
||||
|
||||
Data are saved for specific project or as defaults for all projects.
|
||||
|
||||
Do not use to store whole project settings data with defaults but only
|
||||
it's overrides with metadata defining how overrides should be applied
|
||||
in load function. For loading should be used function
|
||||
`get_studio_project_settings_overrides` for global project settings
|
||||
and `get_project_settings_overrides` for project specific settings.
|
||||
|
||||
Args:
|
||||
project_name(str, null): Project name for which overrides are
|
||||
or None for global settings.
|
||||
data(dict): Data of project overrides with override metadata.
|
||||
"""
|
||||
project_overrides_json_path = self.path_to_project_settings(
|
||||
project_name
|
||||
)
|
||||
dirpath = os.path.dirname(project_overrides_json_path)
|
||||
if not os.path.exists(dirpath):
|
||||
os.makedirs(dirpath)
|
||||
|
||||
self.log.debug(
|
||||
"Saving overrides of project \"{}\". Output path: {}".format(
|
||||
project_name, project_overrides_json_path
|
||||
)
|
||||
)
|
||||
with open(project_overrides_json_path, "w") as file_stream:
|
||||
json.dump(overrides, file_stream, indent=4)
|
||||
|
||||
def save_project_anatomy(self, project_name, anatomy_data):
|
||||
"""Save studio overrides of project anatomy data.
|
||||
|
||||
Args:
|
||||
project_name(str, null): Project name for which overrides are
|
||||
or None for global settings.
|
||||
data(dict): Data of project overrides with override metadata.
|
||||
"""
|
||||
project_anatomy_json_path = self.path_to_project_anatomy(project_name)
|
||||
dirpath = os.path.dirname(project_anatomy_json_path)
|
||||
if not os.path.exists(dirpath):
|
||||
os.makedirs(dirpath)
|
||||
|
||||
self.log.debug(
|
||||
"Saving anatomy of project \"{}\". Output path: {}".format(
|
||||
project_name, project_anatomy_json_path
|
||||
)
|
||||
)
|
||||
with open(project_anatomy_json_path, "w") as file_stream:
|
||||
json.dump(anatomy_data, file_stream, indent=4)
|
||||
|
||||
def get_studio_system_settings_overrides(self):
|
||||
"""Studio overrides of system settings."""
|
||||
if os.path.exists(self.system_settings_path):
|
||||
return self.load_json_file(self.system_settings_path)
|
||||
return {}
|
||||
|
||||
def get_studio_project_settings_overrides(self):
|
||||
"""Studio overrides of default project settings."""
|
||||
if os.path.exists(self.project_settings_path):
|
||||
return self.load_json_file(self.project_settings_path)
|
||||
return {}
|
||||
|
||||
def get_studio_project_anatomy_overrides(self):
|
||||
"""Studio overrides of default project anatomy data."""
|
||||
if os.path.exists(self.project_anatomy_path):
|
||||
return self.load_json_file(self.project_anatomy_path)
|
||||
return {}
|
||||
|
||||
def get_project_settings_overrides(self, project_name):
|
||||
"""Studio overrides of project settings for specific project.
|
||||
|
||||
Args:
|
||||
project_name(str): Name of project for which data should be loaded.
|
||||
|
||||
Returns:
|
||||
dict: Only overrides for entered project, may be empty dictionary.
|
||||
"""
|
||||
path_to_json = self.path_to_project_settings(project_name)
|
||||
if not os.path.exists(path_to_json):
|
||||
return {}
|
||||
return self.load_json_file(path_to_json)
|
||||
|
||||
def get_project_anatomy_overrides(self, project_name):
|
||||
"""Studio overrides of project anatomy for specific project.
|
||||
|
||||
Args:
|
||||
project_name(str): Name of project for which data should be loaded.
|
||||
|
||||
Returns:
|
||||
dict: Only overrides for entered project, may be empty dictionary.
|
||||
"""
|
||||
if not project_name:
|
||||
return {}
|
||||
|
||||
path_to_json = self.path_to_project_anatomy(project_name)
|
||||
if not os.path.exists(path_to_json):
|
||||
return {}
|
||||
return self.load_json_file(path_to_json)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ from .constants import (
|
|||
PROJECT_SETTINGS_KEY,
|
||||
PROJECT_ANATOMY_KEY
|
||||
)
|
||||
from .handlers import (
|
||||
SettingsFileHandler
|
||||
)
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
|
@ -29,6 +31,9 @@ DEFAULTS_DIR = os.path.join(os.path.dirname(__file__), "defaults")
|
|||
# Variable where cache of default settings are stored
|
||||
_DEFAULT_SETTINGS = None
|
||||
|
||||
# Handler of studio overrides
|
||||
SETTINGS_HANDLER = SettingsFileHandler()
|
||||
|
||||
|
||||
class DuplicatedEnvGroups(Exception):
|
||||
def __init__(self, duplicated):
|
||||
|
|
@ -220,150 +225,6 @@ def subkey_merge(_dict, value, keys):
|
|||
return _dict
|
||||
|
||||
|
||||
def path_to_project_settings(project_name):
|
||||
if not project_name:
|
||||
return PROJECT_SETTINGS_PATH
|
||||
return os.path.join(
|
||||
STUDIO_OVERRIDES_PATH,
|
||||
project_name,
|
||||
PROJECT_SETTINGS_FILENAME
|
||||
)
|
||||
|
||||
|
||||
def path_to_project_anatomy(project_name):
|
||||
if not project_name:
|
||||
return PROJECT_ANATOMY_PATH
|
||||
return os.path.join(
|
||||
STUDIO_OVERRIDES_PATH,
|
||||
project_name,
|
||||
PROJECT_ANATOMY_FILENAME
|
||||
)
|
||||
|
||||
|
||||
def save_studio_settings(data):
|
||||
"""Save studio overrides of system settings.
|
||||
|
||||
Do not use to store whole system settings data with defaults but only it's
|
||||
overrides with metadata defining how overrides should be applied in load
|
||||
function. For loading should be used function `studio_system_settings`.
|
||||
|
||||
Args:
|
||||
data(dict): Data of studio overrides with override metadata.
|
||||
"""
|
||||
dirpath = os.path.dirname(SYSTEM_SETTINGS_PATH)
|
||||
if not os.path.exists(dirpath):
|
||||
os.makedirs(dirpath)
|
||||
|
||||
print("Saving studio overrides. Output path: {}".format(
|
||||
SYSTEM_SETTINGS_PATH
|
||||
))
|
||||
with open(SYSTEM_SETTINGS_PATH, "w") as file_stream:
|
||||
json.dump(data, file_stream, indent=4)
|
||||
|
||||
|
||||
def save_project_settings(project_name, overrides):
|
||||
"""Save studio overrides of project settings.
|
||||
|
||||
Data are saved for specific project or as defaults for all projects.
|
||||
|
||||
Do not use to store whole project settings data with defaults but only it's
|
||||
overrides with metadata defining how overrides should be applied in load
|
||||
function. For loading should be used function
|
||||
`get_studio_project_settings_overrides` for global project settings
|
||||
and `get_project_settings_overrides` for project specific settings.
|
||||
|
||||
Args:
|
||||
project_name(str, null): Project name for which overrides are
|
||||
or None for global settings.
|
||||
data(dict): Data of project overrides with override metadata.
|
||||
"""
|
||||
project_overrides_json_path = path_to_project_settings(project_name)
|
||||
dirpath = os.path.dirname(project_overrides_json_path)
|
||||
if not os.path.exists(dirpath):
|
||||
os.makedirs(dirpath)
|
||||
|
||||
print("Saving overrides of project \"{}\". Output path: {}".format(
|
||||
project_name, project_overrides_json_path
|
||||
))
|
||||
with open(project_overrides_json_path, "w") as file_stream:
|
||||
json.dump(overrides, file_stream, indent=4)
|
||||
|
||||
|
||||
def save_project_anatomy(project_name, anatomy_data):
|
||||
"""Save studio overrides of project anatomy data.
|
||||
|
||||
Args:
|
||||
project_name(str, null): Project name for which overrides are
|
||||
or None for global settings.
|
||||
data(dict): Data of project overrides with override metadata.
|
||||
"""
|
||||
project_anatomy_json_path = path_to_project_anatomy(project_name)
|
||||
dirpath = os.path.dirname(project_anatomy_json_path)
|
||||
if not os.path.exists(dirpath):
|
||||
os.makedirs(dirpath)
|
||||
|
||||
print("Saving anatomy of project \"{}\". Output path: {}".format(
|
||||
project_name, project_anatomy_json_path
|
||||
))
|
||||
with open(project_anatomy_json_path, "w") as file_stream:
|
||||
json.dump(anatomy_data, file_stream, indent=4)
|
||||
|
||||
|
||||
def get_studio_system_settings_overrides():
|
||||
"""Studio overrides of system settings."""
|
||||
if os.path.exists(SYSTEM_SETTINGS_PATH):
|
||||
return load_json_file(SYSTEM_SETTINGS_PATH)
|
||||
return {}
|
||||
|
||||
|
||||
def get_studio_project_settings_overrides():
|
||||
"""Studio overrides of default project settings."""
|
||||
if os.path.exists(PROJECT_SETTINGS_PATH):
|
||||
return load_json_file(PROJECT_SETTINGS_PATH)
|
||||
return {}
|
||||
|
||||
|
||||
def get_studio_project_anatomy_overrides():
|
||||
"""Studio overrides of default project anatomy data."""
|
||||
if os.path.exists(PROJECT_ANATOMY_PATH):
|
||||
return load_json_file(PROJECT_ANATOMY_PATH)
|
||||
return {}
|
||||
|
||||
|
||||
def get_project_settings_overrides(project_name):
|
||||
"""Studio overrides of project settings for specific project.
|
||||
|
||||
Args:
|
||||
project_name(str): Name of project for which data should be loaded.
|
||||
|
||||
Returns:
|
||||
dict: Only overrides for entered project, may be empty dictionary.
|
||||
"""
|
||||
|
||||
path_to_json = path_to_project_settings(project_name)
|
||||
if not os.path.exists(path_to_json):
|
||||
return {}
|
||||
return load_json_file(path_to_json)
|
||||
|
||||
|
||||
def get_project_anatomy_overrides(project_name):
|
||||
"""Studio overrides of project anatomy for specific project.
|
||||
|
||||
Args:
|
||||
project_name(str): Name of project for which data should be loaded.
|
||||
|
||||
Returns:
|
||||
dict: Only overrides for entered project, may be empty dictionary.
|
||||
"""
|
||||
if not project_name:
|
||||
return {}
|
||||
|
||||
path_to_json = path_to_project_anatomy(project_name)
|
||||
if not os.path.exists(path_to_json):
|
||||
return {}
|
||||
return load_json_file(path_to_json)
|
||||
|
||||
|
||||
def merge_overrides(source_dict, override_dict):
|
||||
"""Merge data from override_dict to source_dict."""
|
||||
|
||||
|
|
@ -397,7 +258,7 @@ def apply_overrides(source_data, override_data):
|
|||
def get_system_settings(clear_metadata=True):
|
||||
"""System settings with applied studio overrides."""
|
||||
default_values = get_default_settings()[SYSTEM_SETTINGS_KEY]
|
||||
studio_values = get_studio_system_settings_overrides()
|
||||
studio_values = SETTINGS_HANDLER.get_studio_system_settings_overrides()
|
||||
result = apply_overrides(default_values, studio_values)
|
||||
if clear_metadata:
|
||||
clear_metadata_from_settings(result)
|
||||
|
|
@ -407,7 +268,7 @@ def get_system_settings(clear_metadata=True):
|
|||
def get_default_project_settings(clear_metadata=True):
|
||||
"""Project settings with applied studio's default project overrides."""
|
||||
default_values = get_default_settings()[PROJECT_SETTINGS_KEY]
|
||||
studio_values = get_studio_project_settings_overrides()
|
||||
studio_values = SETTINGS_HANDLER.get_studio_project_settings_overrides()
|
||||
result = apply_overrides(default_values, studio_values)
|
||||
if clear_metadata:
|
||||
clear_metadata_from_settings(result)
|
||||
|
|
@ -417,7 +278,7 @@ def get_default_project_settings(clear_metadata=True):
|
|||
def get_default_anatomy_settings(clear_metadata=True):
|
||||
"""Project anatomy data with applied studio's default project overrides."""
|
||||
default_values = get_default_settings()[PROJECT_ANATOMY_KEY]
|
||||
studio_values = get_studio_project_anatomy_overrides()
|
||||
studio_values = SETTINGS_HANDLER.get_studio_project_anatomy_overrides()
|
||||
result = apply_overrides(default_values, studio_values)
|
||||
if clear_metadata:
|
||||
clear_metadata_from_settings(result)
|
||||
|
|
@ -433,7 +294,9 @@ def get_anatomy_settings(project_name, clear_metadata=True):
|
|||
)
|
||||
|
||||
studio_overrides = get_default_anatomy_settings(False)
|
||||
project_overrides = get_project_anatomy_overrides(project_name)
|
||||
project_overrides = SETTINGS_HANDLER.get_project_anatomy_overrides(
|
||||
project_name
|
||||
)
|
||||
|
||||
result = apply_overrides(studio_overrides, project_overrides)
|
||||
if clear_metadata:
|
||||
|
|
@ -450,7 +313,9 @@ def get_project_settings(project_name, clear_metadata=True):
|
|||
)
|
||||
|
||||
studio_overrides = get_default_project_settings(False)
|
||||
project_overrides = get_project_settings_overrides(project_name)
|
||||
project_overrides = SETTINGS_HANDLER.get_project_settings_overrides(
|
||||
project_name
|
||||
)
|
||||
|
||||
result = apply_overrides(studio_overrides, project_overrides)
|
||||
if clear_metadata:
|
||||
|
|
|
|||
|
|
@ -9,21 +9,11 @@ from pype.settings.constants import (
|
|||
)
|
||||
from pype.settings.lib import (
|
||||
DEFAULTS_DIR,
|
||||
SETTINGS_HANDLER,
|
||||
|
||||
reset_default_settings,
|
||||
get_default_settings,
|
||||
|
||||
get_studio_system_settings_overrides,
|
||||
get_studio_project_settings_overrides,
|
||||
get_studio_project_anatomy_overrides,
|
||||
|
||||
get_project_settings_overrides,
|
||||
get_project_anatomy_overrides,
|
||||
|
||||
save_studio_settings,
|
||||
save_project_settings,
|
||||
save_project_anatomy,
|
||||
|
||||
apply_overrides,
|
||||
find_environments,
|
||||
DuplicatedEnvGroups
|
||||
|
|
@ -370,7 +360,7 @@ class SystemWidget(SettingsCategoryWidget):
|
|||
if not self.duplicated_env_group_validation(overrides=values):
|
||||
return
|
||||
|
||||
save_studio_settings(values)
|
||||
SETTINGS_HANDLER.save_studio_settings(values)
|
||||
|
||||
def update_values(self):
|
||||
default_values = lib.convert_data_to_gui_data({
|
||||
|
|
@ -382,8 +372,11 @@ class SystemWidget(SettingsCategoryWidget):
|
|||
if self._hide_studio_overrides:
|
||||
system_values = lib.NOT_SET
|
||||
else:
|
||||
studio_system_overrides = (
|
||||
SETTINGS_HANDLER.get_studio_system_settings_overrides()
|
||||
)
|
||||
system_values = lib.convert_overrides_to_gui_data(
|
||||
{self.main_schema_key: get_studio_system_settings_overrides()}
|
||||
{self.main_schema_key: studio_system_overrides}
|
||||
)
|
||||
|
||||
for input_field in self.input_fields:
|
||||
|
|
@ -547,8 +540,12 @@ class ProjectWidget(SettingsCategoryWidget):
|
|||
_project_anatomy = lib.NOT_SET
|
||||
self.is_overidable = False
|
||||
else:
|
||||
_project_overrides = get_project_settings_overrides(project_name)
|
||||
_project_anatomy = get_project_anatomy_overrides(project_name)
|
||||
_project_overrides = (
|
||||
SETTINGS_HANDLER.get_project_settings_overrides(project_name)
|
||||
)
|
||||
_project_anatomy = (
|
||||
SETTINGS_HANDLER.get_project_anatomy_overrides(project_name)
|
||||
)
|
||||
self.is_overidable = True
|
||||
|
||||
overrides = {self.main_schema_key: {
|
||||
|
|
@ -582,11 +579,15 @@ class ProjectWidget(SettingsCategoryWidget):
|
|||
|
||||
# Saving overrides data
|
||||
project_overrides_data = output_data.get(PROJECT_SETTINGS_KEY, {})
|
||||
save_project_settings(self.project_name, project_overrides_data)
|
||||
SETTINGS_HANDLER.save_project_settings(
|
||||
self.project_name, project_overrides_data
|
||||
)
|
||||
|
||||
# Saving anatomy data
|
||||
project_anatomy_data = output_data.get(PROJECT_ANATOMY_KEY, {})
|
||||
save_project_anatomy(self.project_name, project_anatomy_data)
|
||||
SETTINGS_HANDLER.save_project_anatomy(
|
||||
self.project_name, project_anatomy_data
|
||||
)
|
||||
|
||||
def update_values(self):
|
||||
if self.project_name is not None:
|
||||
|
|
@ -602,14 +603,16 @@ class ProjectWidget(SettingsCategoryWidget):
|
|||
if self._hide_studio_overrides:
|
||||
studio_values = lib.NOT_SET
|
||||
else:
|
||||
project_settings_value = (
|
||||
SETTINGS_HANDLER.get_studio_project_settings_overrides()
|
||||
)
|
||||
project_anatomy_value = (
|
||||
SETTINGS_HANDLER.get_studio_project_anatomy_overrides()
|
||||
)
|
||||
studio_values = lib.convert_overrides_to_gui_data({
|
||||
self.main_schema_key: {
|
||||
PROJECT_SETTINGS_KEY: (
|
||||
get_studio_project_settings_overrides()
|
||||
),
|
||||
PROJECT_ANATOMY_KEY: (
|
||||
get_studio_project_anatomy_overrides()
|
||||
)
|
||||
PROJECT_SETTINGS_KEY: project_settings_value,
|
||||
PROJECT_ANATOMY_KEY: project_anatomy_value
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue