Skip to content

Commit 3b30ce4

Browse files
SG-39225 Support specific keys for entity optimization (#423)
* Support specific keys for entity optimization * Update conditions * Update test * Support lists without dicts on optimization * Improved readability * Improvements by feedback * More granular optimization * Use simple conditions instead of set intersection * Include id and type checks * Make recursive and add more test cases
1 parent b0df9fe commit 3b30ce4

2 files changed

Lines changed: 88 additions & 20 deletions

File tree

shotgun_api3/shotgun.py

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,7 +1194,7 @@ def _translate_update_params(
11941194
def optimize_field(field_dict):
11951195
if SHOTGUN_API_DISABLE_ENTITY_OPTIMIZATION:
11961196
return field_dict
1197-
return {k: _get_type_and_id_from_value(v) for k, v in field_dict.items()}
1197+
return {k: _optimize_filter_field(v) for k, v in field_dict.items()}
11981198

11991199
full_fields = self._dict_to_list(
12001200
data,
@@ -4799,7 +4799,7 @@ def _translate_filters_simple(sg_filter):
47994799
and condition["relation"] in ["is", "is_not", "in", "not_in"]
48004800
and isinstance(values[0], dict)
48014801
):
4802-
values = [_get_type_and_id_from_value(v) for v in values]
4802+
values = [_optimize_filter_field(v) for v in values]
48034803

48044804
condition["values"] = values
48054805

@@ -4813,17 +4813,30 @@ def _version_str(version) -> str:
48134813
return ".".join(map(str, version))
48144814

48154815

4816-
def _get_type_and_id_from_value(value):
4816+
def _optimize_filter_field(
4817+
field_value: Union[dict, list], recursive: bool = True
4818+
) -> Union[dict, list]:
48174819
"""
4818-
For an entity dictionary, returns a new dictionary with only the type and id keys.
4819-
If any of these keys are not present, the original dictionary is returned.
4820+
For an FPT entity, returns a new dictionary with only the type,
4821+
id, and other allowed keys.
4822+
If case of any processing error, the original dictionary is returned.
4823+
4824+
At least `type` and `id` keys are required to do the optimization
48204825
"""
4821-
try:
4822-
if isinstance(value, dict):
4823-
return {"type": value["type"], "id": value["id"]}
4824-
elif isinstance(value, list):
4825-
return [{"type": v["type"], "id": v["id"]} for v in value]
4826-
except (KeyError, TypeError):
4827-
LOG.debug(f"Could not optimize entity value {value}")
4828-
4829-
return value
4826+
allowed_keys = {
4827+
"id",
4828+
"type",
4829+
"url",
4830+
"name",
4831+
"content_type",
4832+
"local_path",
4833+
"storage",
4834+
"relative_path",
4835+
}
4836+
if isinstance(field_value, dict) and "id" in field_value and "type" in field_value:
4837+
return {key: field_value[key] for key in allowed_keys if key in field_value}
4838+
4839+
elif recursive and isinstance(field_value, list):
4840+
return [_optimize_filter_field(fv, recursive=False) for fv in field_value]
4841+
4842+
return field_value

tests/test_unit.py

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -673,33 +673,88 @@ def test_related_object_update_optimization_entity_multi(self):
673673
entity_id = 6626
674674
data = {
675675
"sg_status_list": "ip",
676-
"project": {"id": 70, "type": "Project", "name": "disposable name 70"},
676+
"project": {"id": 70, "type": "Project", "name": "important name 70"},
677677
"sg_vvv": [
678-
{"id": 6441, "type": "Asset", "name": "disposable name 6441"},
679678
{"id": 6440, "type": "Asset"},
679+
{"id": 6441, "type": "Asset", "custom_name": "disposable name 6441"},
680+
{
681+
# To be kept
682+
"id": 6442,
683+
"type": "Asset",
684+
"url": "http://test.com/asset/6442",
685+
# to be removed
686+
"custom_name": "disposable name 1",
687+
"custom_name2": "disposable name 2",
688+
"custom_name3": "disposable name 3",
689+
"custom_name4": "disposable name 4",
690+
},
691+
{
692+
"sg_nested": {
693+
"level1": {
694+
"level2": {"id": 123, "type": "Entity", "foo": "bar"}
695+
}
696+
}
697+
},
680698
],
681699
"sg_class": {
700+
# To be kept
682701
"id": 1,
683702
"type": "CustomEntity53",
684-
"name": "disposable name 1",
703+
"url": "http://test.com",
704+
"name": "important class name",
705+
"local_path": "/some/local/path",
706+
# to be removed
707+
"custom_name": "disposable name 1",
708+
"custom_name2": "disposable name 2",
709+
"custom_name3": "disposable name 3",
710+
"custom_name4": "disposable name 4",
685711
},
686712
}
687713
expected = {
688714
"type": "Asset",
689715
"id": 6626,
690716
"fields": [
691717
{"field_name": "sg_status_list", "value": "ip"},
692-
{"field_name": "project", "value": {"type": "Project", "id": 70}},
718+
{
719+
"field_name": "project",
720+
"value": {
721+
"type": "Project",
722+
"id": 70,
723+
"name": "important name 70",
724+
},
725+
},
693726
{
694727
"field_name": "sg_vvv",
695728
"value": [
696-
{"id": 6441, "type": "Asset"},
697729
{"id": 6440, "type": "Asset"},
730+
{"id": 6441, "type": "Asset"},
731+
{
732+
"id": 6442,
733+
"type": "Asset",
734+
"url": "http://test.com/asset/6442",
735+
},
736+
{
737+
"sg_nested": {
738+
"level1": {
739+
"level2": {
740+
"id": 123,
741+
"type": "Entity",
742+
"foo": "bar",
743+
}
744+
}
745+
}
746+
},
698747
],
699748
},
700749
{
701750
"field_name": "sg_class",
702-
"value": {"type": "CustomEntity53", "id": 1},
751+
"value": {
752+
"type": "CustomEntity53",
753+
"id": 1,
754+
"name": "important class name",
755+
"url": "http://test.com",
756+
"local_path": "/some/local/path",
757+
},
703758
},
704759
],
705760
}

0 commit comments

Comments
 (0)