Skip to content

Commit e473438

Browse files
committed
Pass filters into DatabaseInterface.retrieve
1 parent 2c43ad8 commit e473438

File tree

3 files changed

+32
-23
lines changed

3 files changed

+32
-23
lines changed

financeager/pocket/base.py

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,6 @@ def remove_entry(self, eid, table_name=None):
173173
def get_entries(self, filters=None, recurrent_only=False):
174174
"""Get entries that match the items of the filters dict, if specified.
175175
176-
Constructs a condition from the given filters and uses it to query all tables.
177-
178176
If `recurrent_only` is true, return a list of all entries of the
179177
recurrent table. Filters are applied.
180178
@@ -186,13 +184,10 @@ def get_entries(self, filters=None, recurrent_only=False):
186184
} or
187185
list[dict]
188186
"""
189-
filters = filters or {}
190-
condition = self.db_interface.create_query_condition(**filters)
191-
192187
if recurrent_only:
193-
return self.db_interface.retrieve(RECURRENT_TABLE, condition)
188+
return self.db_interface.retrieve(RECURRENT_TABLE, filters)
194189

195-
return self._search_all_tables(condition)
190+
return self._search_all_tables(filters)
196191

197192
def get_categories(self):
198193
"""Return unique category names in alphabetical order."""
@@ -402,27 +397,41 @@ def _preprocess_entry_for_update(self, *, table_name, raw_data):
402397

403398
return fields
404399

405-
def _search_all_tables(self, condition):
400+
def _search_all_tables(self, filters):
406401
"""Search both the standard table and the recurrent table for elements
407-
that satisfy the given condition.
402+
that satisfy the given filters.
403+
404+
Constructs a condition from the given filters and uses it to query all tables.
408405
409406
The entry IDs are used as key in the returned subdicts.
410407
411-
:param condition: condition for the search
408+
:param filters: filters for the search
412409
:return: dict
413410
"""
414411

415412
elements = {DEFAULT_TABLE: {}, RECURRENT_TABLE: defaultdict(list)}
416413

417-
for element in self.db_interface.retrieve(DEFAULT_TABLE, condition):
414+
for element in self.db_interface.retrieve(DEFAULT_TABLE, filters):
418415
elements[DEFAULT_TABLE][element["eid"]] = element
419416

417+
# Filter keys are name, value, category, and/or date. The first three exist in
418+
# the recurrent table, too, and are hence passed to the retrieve() call.
419+
# Filtering of the date field happens via a lambda function in Python after
420+
# instantiations of recurrent entries have been created.
421+
date_filter = lambda _: True
422+
date_pattern = None
423+
if filters:
424+
date_pattern = filters.pop("date", None)
425+
if date_pattern is not None:
426+
date_pattern = date_pattern.lower()
427+
date_filter = lambda row: date_pattern in row["date"].lower()
428+
420429
# all recurrent elements are generated, and the ones matching the
421430
# condition are appended to a list that is stored under their generating
422431
# element's ID in the 'recurrent' subdictionary
423-
for element in self.db_interface.retrieve(RECURRENT_TABLE):
432+
for element in self.db_interface.retrieve(RECURRENT_TABLE, filters):
424433
for e in self._create_recurrent_elements(element):
425-
if condition(e):
434+
if date_filter(e):
426435
elements[RECURRENT_TABLE][element["eid"]].append(e)
427436

428437
return elements

financeager/pocket/tinydb.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ def __init__(self, *args, **kwargs):
1818
"""
1919
self._db = TinyDB(*args, **kwargs)
2020

21-
def retrieve(self, table_name, condition=None):
22-
if condition is None:
21+
def retrieve(self, table_name, filters=None):
22+
if not filters:
2323
elements = self._db.table(table_name).all()
2424
else:
25+
condition = self.create_query_condition(**filters)
2526
elements = self._db.table(table_name).search(condition)
2627
# Flatten tinydb Documents into dict
2728
return [{**e, **{"eid": e.doc_id}} for e in elements]
@@ -46,9 +47,6 @@ def delete_by_id(self, table_name, element_id):
4647
def create_query_condition(**filters):
4748
""":return: tinydb.queries.QueryInstance (default: noop)"""
4849
condition = Query().noop()
49-
if not filters:
50-
return condition
51-
5250
entry = Query()
5351
for field, pattern in filters.items():
5452
if pattern is None and field in ["category", "end"]:

financeager/pocket/utils.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ class DatabaseInterface(ABC):
88
"""Abstract base class for database client implementations."""
99

1010
@abstractmethod
11-
def retrieve(self, table_name, condition=None) -> Iterable[dict[str, Any]]:
11+
def retrieve(self, table_name, filters=None) -> Iterable[dict[str, Any]]:
1212
"""Retrieve rows from a table.
1313
1414
:param table_name: name of the table to query
15-
:param condition: optional condition to filter rows
15+
:param filters: optional filters dict to filter rows
1616
:return: list of dicts
1717
"""
1818

@@ -59,9 +59,11 @@ def create_query_condition(**filters) -> Any:
5959
"""Construct query condition according to given filters. A filter is
6060
given by a key-value pair. The key indicates the field, the value the
6161
pattern to filter for. Valid keys are 'name', 'date', 'value' and/or
62-
'category'. Patterns must be of type string, or None (only for the fields
63-
'category' and 'end'; indicates filtering for all entries of the default
64-
category, and recurrent entries with indefinite end, resp.).
62+
'category' for the standard table, and 'name', 'value', 'category', 'start',
63+
'end', 'frequency' for the recurrent table.
64+
Patterns must be of type string, or None (only for the fields 'category' and
65+
'end'; indicates filtering for all entries of the default category, and
66+
recurrent entries with indefinite end, resp.).
6567
Return a condition object that is comprehended by the database interface (i.e.
6668
DatabaseInterface.retrieve).
6769
"""

0 commit comments

Comments
 (0)