diff --git a/pype/api.py b/pype/api.py index b88be4cc88..3854da6d30 100644 --- a/pype/api.py +++ b/pype/api.py @@ -1,7 +1,9 @@ from .settings import ( - system_settings, - project_settings, - environments + get_system_settings, + get_project_settings, + get_current_project_settings, + get_anatomy_data, + get_environments ) from pypeapp import ( Logger, @@ -50,9 +52,11 @@ from .lib import ( from .lib import _subprocess as subprocess __all__ = [ - "system_settings", - "project_settings", - "environments", + "get_system_settings", + "get_project_settings", + "get_current_project_settings", + "get_anatomy_data", + "get_environments", "Logger", "Anatomy", diff --git a/pype/lib/applications.py b/pype/lib/applications.py index abc6ca5017..9b6e364a4c 100644 --- a/pype/lib/applications.py +++ b/pype/lib/applications.py @@ -139,7 +139,7 @@ class ApplicationManager: def refresh(self): """Refresh applications from settings.""" - settings = system_settings() + settings = get_system_settings() hosts_definitions = settings["applications"] for app_group, variant_definitions in hosts_definitions.items(): @@ -518,7 +518,7 @@ class ApplicationLaunchContext: # Load settings if were not passed in data settings_env = self.data.get("settings_env") if settings_env is None: - settings_env = environments() + settings_env = get_environments() self.data["settings_env"] = settings_env # subprocess.Popen launch arguments (first argument in constructor) diff --git a/pype/modules_manager.py b/pype/modules_manager.py index 6538187ea9..72023500e4 100644 --- a/pype/modules_manager.py +++ b/pype/modules_manager.py @@ -3,7 +3,7 @@ import inspect import pype.modules from pype.modules import PypeModule -from pype.settings import system_settings +from pype.settings import get_system_settings from pype.api import Logger @@ -24,7 +24,7 @@ class PypeModuleManager: return environments def find_pype_modules(self): - settings = system_settings() + settings = get_system_settings() modules = [] dirpath = os.path.dirname(pype.modules.__file__) for module_name in os.listdir(dirpath): diff --git a/pype/settings/__init__.py b/pype/settings/__init__.py index 7a99ba0b2f..479236b99a 100644 --- a/pype/settings/__init__.py +++ b/pype/settings/__init__.py @@ -1,11 +1,15 @@ from .lib import ( - system_settings, - project_settings, - environments + get_system_settings, + get_project_settings, + get_current_project_settings, + get_anatomy_data, + get_environments ) __all__ = ( - "system_settings", - "project_settings", - "environments" + "get_system_settings", + "get_project_settings", + "get_current_project_settings", + "get_anatomy_data", + "get_environments" ) diff --git a/pype/settings/lib.py b/pype/settings/lib.py index ebd0d86df4..33a427c3a6 100644 --- a/pype/settings/lib.py +++ b/pype/settings/lib.py @@ -5,6 +5,9 @@ import copy log = logging.getLogger(__name__) +# Py2 + Py3 json decode exception +JSON_EXC = getattr(json.decoder, "JSONDecodeError", ValueError) + # Metadata keys for work with studio and project overrides M_OVERRIDEN_KEY = "__overriden_keys__" # Metadata key for storing information about environments @@ -69,7 +72,7 @@ def reset_default_settings(): _DEFAULT_SETTINGS = None -def default_settings(): +def get_default_settings(): global _DEFAULT_SETTINGS if _DEFAULT_SETTINGS is None: _DEFAULT_SETTINGS = load_jsons_from_dir(DEFAULTS_DIR) @@ -82,7 +85,7 @@ def load_json_file(fpath): with open(fpath, "r") as opened_file: return json.load(opened_file) - except json.decoder.JSONDecodeError: + except JSON_EXC: log.warning( "File has invalid json format \"{}\"".format(fpath), exc_info=True @@ -236,27 +239,6 @@ def subkey_merge(_dict, value, keys): return _dict -def studio_system_settings(): - """Studio overrides of system settings.""" - if os.path.exists(SYSTEM_SETTINGS_PATH): - return load_json_file(SYSTEM_SETTINGS_PATH) - return {} - - -def studio_project_settings(): - """Studio overrides of default project settings.""" - if os.path.exists(PROJECT_SETTINGS_PATH): - return load_json_file(PROJECT_SETTINGS_PATH) - return {} - - -def studio_project_anatomy(): - """Studio overrides of default project anatomy data.""" - if os.path.exists(PROJECT_ANATOMY_PATH): - return load_json_file(PROJECT_ANATOMY_PATH) - return {} - - def path_to_project_settings(project_name): if not project_name: return PROJECT_SETTINGS_PATH @@ -305,9 +287,9 @@ def save_project_settings(project_name, overrides): 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 functions `studio_project_settings` - for global project settings and `project_settings_overrides` for - project specific settings. + 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 @@ -346,7 +328,28 @@ def save_project_anatomy(project_name, anatomy_data): json.dump(anatomy_data, file_stream, indent=4) -def project_settings_overrides(project_name): +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: @@ -355,8 +358,6 @@ def project_settings_overrides(project_name): Returns: dict: Only overrides for entered project, may be empty dictionary. """ - if not project_name: - return {} path_to_json = path_to_project_settings(project_name) if not os.path.exists(path_to_json): @@ -364,7 +365,7 @@ def project_settings_overrides(project_name): return load_json_file(path_to_json) -def project_anatomy_overrides(project_name): +def get_project_anatomy_overrides(project_name): """Studio overrides of project anatomy for specific project. Args: @@ -412,26 +413,74 @@ def apply_overrides(source_data, override_data): return merge_overrides(_source_data, override_data) -def system_settings(): +def get_system_settings(): """System settings with applied studio overrides.""" - default_values = default_settings()[SYSTEM_SETTINGS_KEY] - studio_values = studio_system_settings() + default_values = get_default_settings()[SYSTEM_SETTINGS_KEY] + studio_values = get_studio_system_settings_overrides() return apply_overrides(default_values, studio_values) -def project_settings(project_name): - """Project settings with applied studio and project overrides.""" - default_values = default_settings()[PROJECT_SETTINGS_KEY] - studio_values = studio_project_settings() +def get_default_project_settings(): + """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_overrides = apply_overrides(default_values, studio_values) + return apply_overrides(default_values, studio_values) - project_overrides = project_settings_overrides(project_name) + +def get_default_project_anatomy_data(): + """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() + + return apply_overrides(default_values, studio_values) + + +def get_anatomy_data(project_name): + """Project anatomy data with applied studio and project overrides.""" + if not project_name: + raise ValueError( + "Must enter project name." + " Call `get_default_project_anatomy_data` to get project defaults." + ) + + studio_overrides = get_default_project_anatomy_data() + project_overrides = get_project_anatomy_overrides(project_name) return apply_overrides(studio_overrides, project_overrides) -def environments(): +def get_project_settings(project_name): + """Project settings with applied studio and project overrides.""" + if not project_name: + raise ValueError( + "Must enter project name." + " Call `get_default_project_settings` to get project defaults." + ) + + studio_overrides = get_default_project_settings() + project_overrides = get_project_settings_overrides(project_name) + + return apply_overrides(studio_overrides, project_overrides) + + +def get_current_project_settings(): + """Project settings for current context project. + + Project name should be stored in environment variable `AVALON_PROJECT`. + This function should be used only in host context where environment + variable must be set and should not happen that any part of process will + change the value of the enviornment variable. + """ + project_name = os.environ.get("AVALON_PROJECT") + if not project_name: + raise ValueError( + "Missing context project in environemt variable `AVALON_PROJECT`." + ) + return get_project_settings(project_name) + + +def get_environments(): """Calculated environment based on defaults and system settings. Any default environment also found in the system settings will be fully @@ -440,11 +489,5 @@ def environments(): Returns: dict: Output should be ready for `acre` module. """ - # TODO remove these defaults (All should be set with system settings) - envs = copy.deepcopy(default_settings()[ENVIRONMENTS_KEY]) - # This is part of loading environments from settings - envs_from_system_settings = find_environments(system_settings()) - for env_group_key, values in envs_from_system_settings.items(): - envs[env_group_key] = values - return envs + return find_environments(get_system_settings()) diff --git a/pype/tools/settings/settings/widgets/base.py b/pype/tools/settings/settings/widgets/base.py index 9e8e6537f1..5127ea9f88 100644 --- a/pype/tools/settings/settings/widgets/base.py +++ b/pype/tools/settings/settings/widgets/base.py @@ -10,14 +10,14 @@ from pype.settings.lib import ( DEFAULTS_DIR, reset_default_settings, - default_settings, + get_default_settings, - studio_system_settings, - studio_project_settings, - studio_project_anatomy, + get_studio_system_settings_overrides, + get_studio_project_settings_overrides, + get_studio_project_anatomy_overrides, - project_settings_overrides, - project_anatomy_overrides, + get_project_settings_overrides, + get_project_anatomy_overrides, save_studio_settings, save_project_settings, @@ -322,7 +322,7 @@ class SystemWidget(SettingsCategoryWidget): def duplicated_env_group_validation(self, values=None, overrides=None): try: if overrides is not None: - default_values = default_settings()[SYSTEM_SETTINGS_KEY] + default_values = get_default_settings()[SYSTEM_SETTINGS_KEY] values = apply_overrides(default_values, overrides) else: values = copy.deepcopy(values) @@ -375,7 +375,7 @@ class SystemWidget(SettingsCategoryWidget): def update_values(self): default_values = lib.convert_data_to_gui_data({ - self.main_schema_key: default_settings()[SYSTEM_SETTINGS_KEY] + self.main_schema_key: get_default_settings()[SYSTEM_SETTINGS_KEY] }) for input_field in self.input_fields: input_field.update_default_values(default_values) @@ -384,7 +384,7 @@ class SystemWidget(SettingsCategoryWidget): system_values = lib.NOT_SET else: system_values = lib.convert_overrides_to_gui_data( - {self.main_schema_key: studio_system_settings()} + {self.main_schema_key: get_studio_system_settings_overrides()} ) for input_field in self.input_fields: @@ -549,8 +549,8 @@ class ProjectWidget(SettingsCategoryWidget): _project_anatomy = lib.NOT_SET self.is_overidable = False else: - _project_overrides = project_settings_overrides(project_name) - _project_anatomy = project_anatomy_overrides(project_name) + _project_overrides = get_project_settings_overrides(project_name) + _project_anatomy = get_project_anatomy_overrides(project_name) self.is_overidable = True overrides = {self.main_schema_key: { @@ -590,16 +590,16 @@ class ProjectWidget(SettingsCategoryWidget): project_anatomy_data = output_data.get(PROJECT_ANATOMY_KEY, {}) save_project_anatomy(self.project_name, project_anatomy_data) - if self.project_name: - # Refill values with overrides - self._on_project_change() - else: + if studio_overrides: # Update saved values self._update_values() + else: + # Refill values with overrides + self._on_project_change() def update_values(self): default_values = lib.convert_data_to_gui_data( - {self.main_schema_key: default_settings()} + {self.main_schema_key: get_default_settings()} ) for input_field in self.input_fields: input_field.update_default_values(default_values) @@ -609,8 +609,12 @@ class ProjectWidget(SettingsCategoryWidget): else: studio_values = lib.convert_overrides_to_gui_data({ self.main_schema_key: { - PROJECT_SETTINGS_KEY: studio_project_settings(), - PROJECT_ANATOMY_KEY: studio_project_anatomy() + PROJECT_SETTINGS_KEY: ( + get_studio_project_settings_overrides() + ), + PROJECT_ANATOMY_KEY: ( + get_studio_project_anatomy_overrides() + ) } })