mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-01 08:24:53 +01:00
437 lines
15 KiB
Python
437 lines
15 KiB
Python
import os
|
|
import json
|
|
import logging
|
|
from abc import ABCMeta, abstractmethod
|
|
import six
|
|
import pype
|
|
from .constants import (
|
|
SYSTEM_SETTINGS_KEY,
|
|
PROJECT_SETTINGS_KEY,
|
|
PROJECT_ANATOMY_KEY
|
|
)
|
|
|
|
JSON_EXC = getattr(json.decoder, "JSONDecodeError", ValueError)
|
|
|
|
|
|
@six.add_metaclass(ABCMeta)
|
|
class SettingsHandler:
|
|
@abstractmethod
|
|
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.
|
|
"""
|
|
pass
|
|
|
|
@abstractmethod
|
|
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.
|
|
"""
|
|
pass
|
|
|
|
@abstractmethod
|
|
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.
|
|
"""
|
|
pass
|
|
|
|
@abstractmethod
|
|
def get_studio_system_settings_overrides(self):
|
|
"""Studio overrides of system settings."""
|
|
pass
|
|
|
|
@abstractmethod
|
|
def get_studio_project_settings_overrides(self):
|
|
"""Studio overrides of default project settings."""
|
|
pass
|
|
|
|
@abstractmethod
|
|
def get_studio_project_anatomy_overrides(self):
|
|
"""Studio overrides of default project anatomy data."""
|
|
pass
|
|
|
|
@abstractmethod
|
|
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.
|
|
"""
|
|
pass
|
|
|
|
@abstractmethod
|
|
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.
|
|
"""
|
|
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)
|
|
|
|
|
|
class MongoSettingsHandler(SettingsHandler):
|
|
"""Settings handler that use mongo for storing and loading of settings."""
|
|
system_settings_key = "system_settings"
|
|
project_anatomy_key = "project_anatomy"
|
|
project_settings_key = "project_settings"
|
|
|
|
def __init__(self):
|
|
# Get mongo connection
|
|
from pype.lib import PypeMongoConnection
|
|
settings_collection = PypeMongoConnection.get_mongo_client()
|
|
|
|
# TODO prepare version of pype
|
|
# - pype version should define how are settings saved and loaded
|
|
|
|
# TODO modify to not use hardcoded keys
|
|
database_name = "pype"
|
|
collection_name = "settings"
|
|
|
|
self.settings_collection = settings_collection
|
|
|
|
self.database_name = database_name
|
|
self.collection_name = collection_name
|
|
|
|
self.collection = settings_collection[database_name][collection_name]
|
|
|
|
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.
|
|
"""
|
|
self.collection.replace_one(
|
|
{
|
|
"type": self.system_settings_key
|
|
},
|
|
{
|
|
"type": self.system_settings_key,
|
|
"value": data
|
|
}
|
|
)
|
|
|
|
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.
|
|
"""
|
|
|
|
self.collection.replace_one(
|
|
{
|
|
"type": self.project_settings_key,
|
|
"project_name": project_name
|
|
},
|
|
{
|
|
"type": self.project_settings_key,
|
|
"project_name": project_name,
|
|
"value": overrides
|
|
}
|
|
)
|
|
|
|
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.
|
|
"""
|
|
self.collection.replace_one(
|
|
{
|
|
"type": self.project_anatomy_key,
|
|
"project_name": project_name
|
|
},
|
|
{
|
|
"type": self.project_anatomy_key,
|
|
"project_name": project_name,
|
|
"value": anatomy_data
|
|
}
|
|
)
|
|
|
|
def get_studio_system_settings_overrides(self):
|
|
"""Studio overrides of system settings."""
|
|
return self.collection.find_one({
|
|
"type": self.system_settings_key
|
|
}) or {}
|
|
|
|
def get_studio_project_settings_overrides(self):
|
|
"""Studio overrides of default project settings."""
|
|
return self.collection.find_one({
|
|
"type": self.project_settings_key,
|
|
"project_name": None
|
|
}) or {}
|
|
|
|
def get_studio_project_anatomy_overrides(self):
|
|
"""Studio overrides of default project anatomy data."""
|
|
return self.collection.find_one({
|
|
"type": self.project_anatomy_key,
|
|
"project_name": None
|
|
}) or {}
|
|
|
|
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.
|
|
"""
|
|
if not project_name:
|
|
return {}
|
|
return self.collection.find_one({
|
|
"type": self.project_settings_key,
|
|
"project_name": project_name
|
|
}) or {}
|
|
|
|
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 {}
|
|
return self.collection.find_one({
|
|
"type": self.project_anatomy_key,
|
|
"project_name": project_name
|
|
}) or {}
|