From c51004253bfa59231d5b03fea373436010471dea Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 22 Apr 2022 06:00:22 -0500 Subject: [PATCH] refactor(ListQuery): Pure list --- libvcs/utils/query_list.py | 38 +++++++++++----------------------- tests/utils/test_query_list.py | 2 +- 2 files changed, 13 insertions(+), 27 deletions(-) diff --git a/libvcs/utils/query_list.py b/libvcs/utils/query_list.py index 4d0a4c50..6c6456df 100644 --- a/libvcs/utils/query_list.py +++ b/libvcs/utils/query_list.py @@ -1,7 +1,6 @@ -import dataclasses import re import traceback -from typing import Any, Callable, Generic, Optional, Protocol, Sequence, TypeVar, Union +from typing import Any, Callable, Optional, Protocol, Sequence, TypeVar, Union T = TypeVar("T", Any, Any) @@ -121,13 +120,9 @@ def lookup_iregex(data, rhs): } -@dataclasses.dataclass(eq=False) -class QueryList(Generic[T]): +class QueryList(list[T]): """Filter list of object/dicts. For small, local datasets. *Experimental, unstable*. - :py:func:`dataclasses.dataclass` is only used for ``__repr__`` and pytest comparison - details. - >>> query = QueryList( ... [ ... { @@ -144,44 +139,35 @@ class QueryList(Generic[T]): ... }, ... ] ... ) - >>> query.filter(place="Chicago suburbs").data[0]['city'] + >>> query.filter(place="Chicago suburbs")[0]['city'] 'Elmhurst' - >>> query.filter(place__icontains="chicago").data[0]['city'] + >>> query.filter(place__icontains="chicago")[0]['city'] 'Elmhurst' - >>> query.filter(foods__breakfast="waffles").data[0]['city'] + >>> query.filter(foods__breakfast="waffles")[0]['city'] 'Elmhurst' - >>> query.filter(foods__fruit__in="cantelope").data[0]['city'] + >>> query.filter(foods__fruit__in="cantelope")[0]['city'] 'Elmhurst' - >>> query.filter(foods__fruit__in="orange").data[0]['city'] + >>> query.filter(foods__fruit__in="orange")[0]['city'] 'Tampa' """ - __slots__ = ("data", "pk_key") data: Sequence[T] - # def __init__(self, data, pk_key: Optional[str] = None): - # self.data: Sequence[T] = data - # #: Primary key for objects, optional. - # #: Use for .get(), .items() - # self.pk_key: Optional[Any] = pk_key - def items(self): data: Sequence[T] if self.pk_key is None: raise Exception("items() require a pk_key exists") - return [(getattr(item, self.pk_key), item) for item in self.data] + return [(getattr(item, self.pk_key), item) for item in self] def __eq__(self, other): data = other - if hasattr(data, "data"): - data = getattr(data, "data") - if not isinstance(self.data, list) or not isinstance(data, list): + if not isinstance(self, list) or not isinstance(data, list): return False - if len(self.data) == len(data): - for (a, b) in zip(self.data, data): + if len(self) == len(data): + for (a, b) in zip(self, data): if isinstance(a, dict): a_keys = a.keys() if a.keys == b.keys(): @@ -230,4 +216,4 @@ def val_match(obj): else: _filter = filter_lookup - return self.__class__(data=[k for k in self.data if _filter(k)]) + return self.__class__(k for k in self if _filter(k)) diff --git a/tests/utils/test_query_list.py b/tests/utils/test_query_list.py index a2b597cb..6e0da2b1 100644 --- a/tests/utils/test_query_list.py +++ b/tests/utils/test_query_list.py @@ -230,7 +230,7 @@ ], ) def test_filter(items: list, filter_expr: Optional[dict], expected_result: list): - qs = QueryList(data=items) + qs = QueryList(items) if filter_expr is not None: if isinstance(filter_expr, dict): assert qs.filter(**filter_expr) == expected_result