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

Settings: Conditional dictionary avoid invalid logs #2956

Merged
merged 3 commits into from
Mar 28, 2022
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
37 changes: 24 additions & 13 deletions openpype/settings/entities/base_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@ def __init__(self, schema_data):
# Entity has set `_project_override_value` (is not NOT_SET)
self.had_project_override = False

self._default_log_invalid_types = True
self._studio_log_invalid_types = True
self._project_log_invalid_types = True

# Callbacks that are called on change.
# - main current purspose is to register GUI callbacks
self.on_change_callbacks = []
Expand Down Expand Up @@ -419,7 +423,7 @@ def convert_to_valid_type(self, value):
raise InvalidValueType(self.valid_value_types, type(value), self.path)

# TODO convert to private method
def _check_update_value(self, value, value_source):
def _check_update_value(self, value, value_source, log_invalid_types=True):
"""Validation of value on update methods.

Update methods update data from currently saved settings so it is
Expand Down Expand Up @@ -447,16 +451,17 @@ def _check_update_value(self, value, value_source):
if new_value is not NOT_SET:
return new_value

# Warning log about invalid value type.
self.log.warning(
(
"{} Got invalid value type for {} values."
" Expected types: {} | Got Type: {} | Value: \"{}\""
).format(
self.path, value_source,
self.valid_value_types, type(value), str(value)
if log_invalid_types:
# Warning log about invalid value type.
self.log.warning(
(
"{} Got invalid value type for {} values."
" Expected types: {} | Got Type: {} | Value: \"{}\""
).format(
self.path, value_source,
self.valid_value_types, type(value), str(value)
)
)
)
return NOT_SET

def available_for_role(self, role_name=None):
Expand Down Expand Up @@ -985,7 +990,7 @@ def get_entity_from_path(self, path):
return self.root_item.get_entity_from_path(path)

@abstractmethod
def update_default_value(self, parent_values):
def update_default_value(self, parent_values, log_invalid_types=True):
"""Fill default values on startup or on refresh.

Default values stored in `openpype` repository should update all items
Expand All @@ -995,11 +1000,13 @@ def update_default_value(self, parent_values):
Args:
parent_values (dict): Values of parent's item. But in case item is
used as widget, `parent_values` contain value for item.
log_invalid_types (bool): Log invalid type of value. Used when
entity can have children with same keys and different types.
"""
pass

@abstractmethod
def update_studio_value(self, parent_values):
def update_studio_value(self, parent_values, log_invalid_types=True):
"""Fill studio override values on startup or on refresh.

Set studio value if is not set to NOT_SET, in that case studio
Expand All @@ -1008,11 +1015,13 @@ def update_studio_value(self, parent_values):
Args:
parent_values (dict): Values of parent's item. But in case item is
used as widget, `parent_values` contain value for item.
log_invalid_types (bool): Log invalid type of value. Used when
entity can have children with same keys and different types.
"""
pass

@abstractmethod
def update_project_value(self, parent_values):
def update_project_value(self, parent_values, log_invalid_types=True):
"""Fill project override values on startup, refresh or project change.

Set project value if is not set to NOT_SET, in that case project
Expand All @@ -1021,5 +1030,7 @@ def update_project_value(self, parent_values):
Args:
parent_values (dict): Values of parent's item. But in case item is
used as widget, `parent_values` contain value for item.
log_invalid_types (bool): Log invalid type of value. Used when
entity can have children with same keys and different types.
"""
pass
86 changes: 58 additions & 28 deletions openpype/settings/entities/dict_conditional.py
Original file line number Diff line number Diff line change
Expand Up @@ -518,12 +518,18 @@ def settings_value(self):
output.update(self._current_metadata)
return output

def _prepare_value(self, value):
def _prepare_value(self, value, log_invalid_types):
if value is NOT_SET or self.enum_key not in value:
return NOT_SET, NOT_SET

enum_value = value.get(self.enum_key)
if enum_value not in self.non_gui_children:
if log_invalid_types:
self.log.warning(
"{} Unknown enum key in default values: {}".format(
self.path, enum_value
)
)
return NOT_SET, NOT_SET

# Create copy of value before poping values
Expand Down Expand Up @@ -551,117 +557,141 @@ def _prepare_value(self, value):

return value, metadata

def update_default_value(self, value):
def update_default_value(self, value, log_invalid_types=True):
"""Update default values.

Not an api method, should be called by parent.
"""
value = self._check_update_value(value, "default")
self._default_log_invalid_types = log_invalid_types
value = self._check_update_value(
value, "default", log_invalid_types
)
self.has_default_value = value is not NOT_SET
# TODO add value validation
value, metadata = self._prepare_value(value)
value, metadata = self._prepare_value(value, log_invalid_types)
self._default_metadata = metadata

if value is NOT_SET:
self.enum_entity.update_default_value(value)
self.enum_entity.update_default_value(value, log_invalid_types)
for children_by_key in self.non_gui_children.values():
for child_obj in children_by_key.values():
child_obj.update_default_value(value)
child_obj.update_default_value(value, log_invalid_types)
return

value_keys = set(value.keys())
enum_value = value[self.enum_key]
expected_keys = set(self.non_gui_children[enum_value].keys())
expected_keys.add(self.enum_key)
unknown_keys = value_keys - expected_keys
if unknown_keys:
if unknown_keys and log_invalid_types:
self.log.warning(
"{} Unknown keys in default values: {}".format(
self.path,
", ".join("\"{}\"".format(key) for key in unknown_keys)
)
)

self.enum_entity.update_default_value(enum_value)
for children_by_key in self.non_gui_children.values():
self.enum_entity.update_default_value(enum_value, log_invalid_types)

for enum_key, children_by_key in self.non_gui_children.items():
_log_invalid_types = log_invalid_types
if _log_invalid_types:
_log_invalid_types = enum_key == enum_value

value_copy = copy.deepcopy(value)
for key, child_obj in children_by_key.items():
child_value = value_copy.get(key, NOT_SET)
child_obj.update_default_value(child_value)
child_obj.update_default_value(child_value, _log_invalid_types)

def update_studio_value(self, value):
def update_studio_value(self, value, log_invalid_types=True):
"""Update studio override values.

Not an api method, should be called by parent.
"""
value = self._check_update_value(value, "studio override")
value, metadata = self._prepare_value(value)

self._studio_log_invalid_types = log_invalid_types
value = self._check_update_value(
value, "studio override", log_invalid_types
)
value, metadata = self._prepare_value(value, log_invalid_types)
self._studio_override_metadata = metadata
self.had_studio_override = metadata is not NOT_SET

if value is NOT_SET:
self.enum_entity.update_studio_value(value)
self.enum_entity.update_studio_value(value, log_invalid_types)
for children_by_key in self.non_gui_children.values():
for child_obj in children_by_key.values():
child_obj.update_studio_value(value)
child_obj.update_studio_value(value, log_invalid_types)
return

value_keys = set(value.keys())
enum_value = value[self.enum_key]
expected_keys = set(self.non_gui_children[enum_value])
expected_keys.add(self.enum_key)
unknown_keys = value_keys - expected_keys
if unknown_keys:
if unknown_keys and log_invalid_types:
self.log.warning(
"{} Unknown keys in studio overrides: {}".format(
self.path,
", ".join("\"{}\"".format(key) for key in unknown_keys)
)
)

self.enum_entity.update_studio_value(enum_value)
for children_by_key in self.non_gui_children.values():
self.enum_entity.update_studio_value(enum_value, log_invalid_types)
for enum_key, children_by_key in self.non_gui_children.items():
_log_invalid_types = log_invalid_types
if _log_invalid_types:
_log_invalid_types = enum_key == enum_value

value_copy = copy.deepcopy(value)
for key, child_obj in children_by_key.items():
child_value = value_copy.get(key, NOT_SET)
child_obj.update_studio_value(child_value)
child_obj.update_studio_value(child_value, _log_invalid_types)

def update_project_value(self, value):
def update_project_value(self, value, log_invalid_types=True):
"""Update project override values.

Not an api method, should be called by parent.
"""
value = self._check_update_value(value, "project override")
value, metadata = self._prepare_value(value)

self._project_log_invalid_types = log_invalid_types
value = self._check_update_value(
value, "project override", log_invalid_types
)
value, metadata = self._prepare_value(value, log_invalid_types)
self._project_override_metadata = metadata
self.had_project_override = metadata is not NOT_SET

if value is NOT_SET:
self.enum_entity.update_project_value(value)
self.enum_entity.update_project_value(value, log_invalid_types)
for children_by_key in self.non_gui_children.values():
for child_obj in children_by_key.values():
child_obj.update_project_value(value)
child_obj.update_project_value(value, log_invalid_types)
return

value_keys = set(value.keys())
enum_value = value[self.enum_key]
expected_keys = set(self.non_gui_children[enum_value])
expected_keys.add(self.enum_key)
unknown_keys = value_keys - expected_keys
if unknown_keys:
if unknown_keys and log_invalid_types:
self.log.warning(
"{} Unknown keys in project overrides: {}".format(
self.path,
", ".join("\"{}\"".format(key) for key in unknown_keys)
)
)

self.enum_entity.update_project_value(enum_value)
for children_by_key in self.non_gui_children.values():
self.enum_entity.update_project_value(enum_value, log_invalid_types)
for enum_key, children_by_key in self.non_gui_children.items():
_log_invalid_types = log_invalid_types
if _log_invalid_types:
_log_invalid_types = enum_key == enum_value

value_copy = copy.deepcopy(value)
for key, child_obj in children_by_key.items():
child_value = value_copy.get(key, NOT_SET)
child_obj.update_project_value(child_value)
child_obj.update_project_value(child_value, _log_invalid_types)

def _discard_changes(self, on_change_trigger):
self._ignore_child_changes = True
Expand Down
Loading