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

Commit

Permalink
Merge pull request #2956 from pypeclub/bugfix/conditional_dict_invali…
Browse files Browse the repository at this point in the history
…d_logs

Settings: Conditional dictionary avoid invalid logs
  • Loading branch information
iLLiCiTiT authored Mar 28, 2022
2 parents 2c427a1 + 5acdf2a commit 50550c5
Show file tree
Hide file tree
Showing 7 changed files with 268 additions and 129 deletions.
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

0 comments on commit 50550c5

Please sign in to comment.