Skip to content

Commit

Permalink
feat: avoid fetching and iterating convert keys when empty (#48)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdraco authored Jun 13, 2024
1 parent 486e3f9 commit 7c9ae89
Showing 1 changed file with 87 additions and 62 deletions.
149 changes: 87 additions & 62 deletions src/uiprotect/data/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,26 +141,32 @@ def construct(cls, _fields_set: set[str] | None = None, **values: Any) -> Self:
api: ProtectApiClient | None = values.pop("api", None)
values_set = set(values)

unifi_objs = cls._get_protect_objs()
for key in cls._get_protect_objs_set().intersection(values_set):
if isinstance(values[key], dict):
values[key] = unifi_objs[key].construct(**values[key])

unifi_lists = cls._get_protect_lists()
for key in cls._get_protect_lists_set().intersection(values_set):
if isinstance(values[key], list):
values[key] = [
unifi_lists[key].construct(**v) if isinstance(v, dict) else v
for v in values[key]
]

unifi_dicts = cls._get_protect_dicts()
for key in cls._get_protect_dicts_set().intersection(values_set):
if isinstance(values[key], dict):
values[key] = {
k: unifi_dicts[key].construct(**v) if isinstance(v, dict) else v
for k, v in values[key].items()
}
if (unifi_objs := cls._get_protect_objs()) and (
intersections := cls._get_protect_objs_set().intersection(values_set)
):
for key in intersections:
if isinstance(values[key], dict):
values[key] = unifi_objs[key].construct(**values[key])

if (unifi_lists := cls._get_protect_lists()) and (
intersections := cls._get_protect_lists_set().intersection(values_set)
):
for key in intersections:
if isinstance(values[key], list):
values[key] = [
unifi_lists[key].construct(**v) if isinstance(v, dict) else v
for v in values[key]
]

if (unifi_dicts := cls._get_protect_dicts()) and (
intersections := cls._get_protect_dicts_set().intersection(values_set)
):
for key in intersections:
if isinstance(values[key], dict):
values[key] = {
k: unifi_dicts[key].construct(**v) if isinstance(v, dict) else v
for k, v in values[key].items()
}

obj = super().construct(_fields_set=_fields_set, **values)
if api is not None:
Expand Down Expand Up @@ -336,11 +342,14 @@ def unifi_dict_to_dict(cls, data: dict[str, Any]) -> dict[str, Any]:
)

# remap keys that will not be converted correctly by snake_case convert
remaps = cls._get_unifi_remaps()
for from_key in cls._get_unifi_remaps_set().intersection(data):
data[remaps[from_key]] = data.pop(from_key)
if (remaps := cls._get_unifi_remaps()) and (
intersections := cls._get_unifi_remaps_set().intersection(data)
):
for from_key in intersections:
data[remaps[from_key]] = data.pop(from_key)

# convert to snake_case and remove extra fields
_fields = cls.__fields__
for key in list(data):
new_key = to_snake_case(key)
data[new_key] = data.pop(key)
Expand All @@ -349,35 +358,41 @@ def unifi_dict_to_dict(cls, data: dict[str, Any]) -> dict[str, Any]:
if key == "api":
continue

if key not in cls.__fields__:
if key not in _fields:
del data[key]
continue
data[key] = convert_unifi_data(data[key], cls.__fields__[key])
data[key] = convert_unifi_data(data[key], _fields[key])

# clean child UFP objs
data_set = set(data)

unifi_objs = cls._get_protect_objs()
for key in cls._get_protect_objs_set().intersection(data_set):
data[key] = cls._clean_protect_obj(data[key], unifi_objs[key], api)

unifi_lists = cls._get_protect_lists()
for key in cls._get_protect_lists_set().intersection(data_set):
if isinstance(data[key], list):
data[key] = cls._clean_protect_obj_list(
data[key],
unifi_lists[key],
api,
)
if (unifi_objs := cls._get_protect_objs()) and (
intersections := cls._get_protect_objs_set().intersection(data_set)
):
for key in intersections:
data[key] = cls._clean_protect_obj(data[key], unifi_objs[key], api)

unifi_dicts = cls._get_protect_dicts()
for key in cls._get_protect_dicts_set().intersection(data_set):
if isinstance(data[key], dict):
data[key] = cls._clean_protect_obj_dict(
data[key],
unifi_dicts[key],
api,
)
if (unifi_lists := cls._get_protect_lists()) and (
intersections := cls._get_protect_lists_set().intersection(data_set)
):
for key in intersections:
if isinstance(data[key], list):
data[key] = cls._clean_protect_obj_list(
data[key],
unifi_lists[key],
api,
)

if (unifi_dicts := cls._get_protect_dicts()) and (
intersections := cls._get_protect_dicts_set().intersection(data_set)
):
for key in intersections:
if isinstance(data[key], dict):
data[key] = cls._clean_protect_obj_dict(
data[key],
unifi_dicts[key],
api,
)

return data

Expand Down Expand Up @@ -505,24 +520,34 @@ def _inject_api(
data["api"] = api
data_set = set(data)

for key in self._get_protect_objs_set().intersection(data_set):
unifi_obj: Any | None = getattr(self, key)
if unifi_obj is not None and isinstance(unifi_obj, dict):
unifi_obj["api"] = api
if (unifi_objs_sets := self._get_protect_objs_set()) and (
intersections := unifi_objs_sets.intersection(data_set)
):
for key in intersections:
unifi_obj: Any | None = getattr(self, key)
if unifi_obj is not None and isinstance(unifi_obj, dict):
unifi_obj["api"] = api

for key in self._get_protect_lists_set().intersection(data_set):
new_items = []
for item in data[key]:
if isinstance(item, dict):
item["api"] = api
new_items.append(item)
data[key] = new_items

for key in self._get_protect_dicts_set().intersection(data_set):
for item_key, item in data[key].items():
if isinstance(item, dict):
item["api"] = api
data[key][item_key] = item
if (unifi_lists_sets := self._get_protect_lists_set()) and (
intersections := unifi_lists_sets.intersection(data_set)
):
for key in intersections:
new_items = []
for item in data[key]:
if isinstance(item, dict):
item["api"] = api
new_items.append(item)
data[key] = new_items

if (unifi_dicts_sets := self._get_protect_dicts_set()) and (
intersections := unifi_dicts_sets.intersection(data_set)
):
for key in intersections:
inner_dict: dict[str, Any] = data[key]
for item_key, item in inner_dict.items():
if isinstance(item, dict):
item["api"] = api
inner_dict[item_key] = item

return data

Expand Down

0 comments on commit 7c9ae89

Please sign in to comment.