Skip to content

Commit 79cdef3

Browse files
committed
Add a 'retired' parameter to Class.filter
.. to allow searching for retired, non-retired or all (retired and non-retired) items similar to the argument of the same name to Class.getnodeids. This is 'False' by default (finding only non-retired items for backwards compatibility) and can be set to None (for finding retired and non-retired items) or True (for finding only retired items).
1 parent d54a7f5 commit 79cdef3

File tree

6 files changed

+58
-19
lines changed

6 files changed

+58
-19
lines changed

CHANGES.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,12 @@ Features:
222222
bounced back to the sender with an error. Enable by configuring the
223223
convert_htmltotext option in your upgraded config.ini. (Initial
224224
patch by Igor Ippolitov merged with changes by John Rouillard.)
225+
- Add a 'retired' parameter to Class.filter to allow searching for
226+
retired, non-retired or all (retired and non-retired) items similar
227+
to the argument of the same name to Class.getnodeids. This is 'False'
228+
by default (finding only non-retired items for backwards
229+
compatibility) and can be set to None (for finding retired and
230+
non-retired items) or True (for finding only retired items).
225231

226232
Fixed:
227233

roundup/backends/back_anydbm.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1683,8 +1683,8 @@ def getnodeids(self, db=None, retired=None):
16831683
return res
16841684

16851685
def _filter(self, search_matches, filterspec, proptree,
1686-
num_re = re.compile('^\d+$')):
1687-
"""Return a list of the ids of the active nodes in this class that
1686+
num_re = re.compile('^\d+$'), retired=False):
1687+
"""Return a list of the ids of the nodes in this class that
16881688
match the 'filter' spec, sorted by the group spec and then the
16891689
sort spec.
16901690
@@ -1695,6 +1695,9 @@ def _filter(self, search_matches, filterspec, proptree,
16951695
16961696
"search_matches" is a sequence type or None
16971697
1698+
"retired" specifies if we should find only non-retired nodes
1699+
(default) or only retired node (value True) or all nodes.
1700+
16981701
The filter must match all properties specificed. If the property
16991702
value to match is a list:
17001703
@@ -1795,16 +1798,14 @@ def _filter(self, search_matches, filterspec, proptree,
17951798

17961799
filterspec = l
17971800

1798-
# now, find all the nodes that are active and pass filtering
1801+
# now, find all the nodes that pass filtering
17991802
matches = []
18001803
cldb = self.db.getclassdb(cn)
18011804
t = 0
18021805
try:
18031806
# TODO: only full-scan once (use items())
1804-
for nodeid in self.getnodeids(cldb):
1807+
for nodeid in self.getnodeids(cldb, retired=retired):
18051808
node = self.db.getnode(cn, nodeid, cldb)
1806-
if self.db.RETIRED_FLAG in node:
1807-
continue
18081809
# apply filter
18091810
for t, k, v in filterspec:
18101811
# handle the id prop

roundup/backends/back_sqlite.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,12 +439,12 @@ def load_journal(self, classname, cols, nodeid):
439439

440440
class sqliteClass:
441441
def filter(self, search_matches, filterspec, sort=(None,None),
442-
group=(None,None)):
442+
group=(None,None), retired=False):
443443
""" If there's NO matches to a fetch, sqlite returns NULL
444444
instead of nothing
445445
"""
446446
return [f for f in rdbms_common.Class.filter(self, search_matches,
447-
filterspec, sort=sort, group=group) if f]
447+
filterspec, sort=sort, group=group, retired=retired) if f]
448448

449449
class Class(sqliteClass, rdbms_common.Class):
450450
pass

roundup/backends/rdbms_common.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2381,7 +2381,8 @@ def collect_values(n): values.append(n.x)
23812381
multilink_table, ','.join([self.db.arg] * len(v)))
23822382
return where, v, True # True to indicate original
23832383

2384-
def _filter_sql (self, search_matches, filterspec, srt=[], grp=[], retr=0):
2384+
def _filter_sql (self, search_matches, filterspec, srt=[], grp=[], retr=0,
2385+
retired=False):
23852386
""" Compute the proptree and the SQL/ARGS for a filter.
23862387
For argument description see filter below.
23872388
We return a 3-tuple, the proptree, the sql and the sql-args
@@ -2650,7 +2651,11 @@ def _filter_sql (self, search_matches, filterspec, srt=[], grp=[], retr=0):
26502651
props = self.getprops()
26512652

26522653
# don't match retired nodes
2653-
where.append('_%s.__retired__=0'%icn)
2654+
if retired is not None:
2655+
op = '='
2656+
if retired:
2657+
op = '!='
2658+
where.append('_%s.__retired__%s0'%(icn, op))
26542659

26552660
# add results of full text search
26562661
if search_matches is not None:
@@ -2688,7 +2693,8 @@ def _filter_sql (self, search_matches, filterspec, srt=[], grp=[], retr=0):
26882693
__traceback_info__ = (sql, args)
26892694
return proptree, sql, args
26902695

2691-
def filter(self, search_matches, filterspec, sort=[], group=[]):
2696+
def filter(self, search_matches, filterspec, sort=[], group=[],
2697+
retired=False):
26922698
"""Return a list of the ids of the active nodes in this class that
26932699
match the 'filter' spec, sorted by the group spec and then the
26942700
sort spec
@@ -2711,7 +2717,8 @@ def filter(self, search_matches, filterspec, sort=[], group=[]):
27112717
if __debug__:
27122718
start_t = time.time()
27132719

2714-
sq = self._filter_sql (search_matches, filterspec, sort, group)
2720+
sq = self._filter_sql (search_matches, filterspec, sort, group,
2721+
retired=retired)
27152722
# nothing to match?
27162723
if sq is None:
27172724
return []
@@ -2734,7 +2741,8 @@ def filter(self, search_matches, filterspec, sort=[], group=[]):
27342741
self.db.stats['filtering'] += (time.time() - start_t)
27352742
return l
27362743

2737-
def filter_iter(self, search_matches, filterspec, sort=[], group=[]):
2744+
def filter_iter(self, search_matches, filterspec, sort=[], group=[],
2745+
retired=False):
27382746
"""Iterator similar to filter above with same args.
27392747
Limitation: We don't sort on multilinks.
27402748
This uses an optimisation: We put all nodes that are in the
@@ -2743,7 +2751,8 @@ def filter_iter(self, search_matches, filterspec, sort=[], group=[]):
27432751
a join) from the database because the nodes are already in the
27442752
cache. We're using our own temporary cursor.
27452753
"""
2746-
sq = self._filter_sql(search_matches, filterspec, sort, group, retr=1)
2754+
sq = self._filter_sql(search_matches, filterspec, sort, group, retr=1,
2755+
retired=retired)
27472756
# nothing to match?
27482757
if sq is None:
27492758
return

roundup/hyperdb.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ def ancestors(self):
452452
yield p
453453
p = p.parent
454454

455-
def search(self, search_matches=None, sort=True):
455+
def search(self, search_matches=None, sort=True, retired=False):
456456
""" Recursively search for the given properties in a proptree.
457457
Once all properties are non-transitive, the search generates a
458458
simple _filter call which does the real work
@@ -463,7 +463,8 @@ def search(self, search_matches=None, sort=True):
463463
if p.children:
464464
p.search(sort = False)
465465
filterspec[p.name] = p.val
466-
self.val = self.cls._filter(search_matches, filterspec, sort and self)
466+
self.val = self.cls._filter(search_matches, filterspec, sort and self,
467+
retired=retired)
467468
return self.val
468469

469470
def sort (self, ids=None):
@@ -1255,7 +1256,7 @@ def find(self, **propspec):
12551256
raise NotImplementedError
12561257

12571258
def _filter(self, search_matches, filterspec, sort=(None,None),
1258-
group=(None,None)):
1259+
group=(None,None), retired=False):
12591260
"""For some backends this implements the non-transitive
12601261
search, for more information see the filter method.
12611262
"""
@@ -1346,7 +1347,8 @@ def _sortattr(self, sort=[], group=[]):
13461347
sortattr.append(('+', 'id'))
13471348
return sortattr
13481349

1349-
def filter(self, search_matches, filterspec, sort=[], group=[]):
1350+
def filter(self, search_matches, filterspec, sort=[], group=[],
1351+
retired=False):
13501352
"""Return a list of the ids of the active nodes in this class that
13511353
match the 'filter' spec, sorted by the group spec and then the
13521354
sort spec.
@@ -1382,7 +1384,7 @@ def filter(self, search_matches, filterspec, sort=[], group=[]):
13821384
"""
13831385
sortattr = self._sortattr(sort = sort, group = group)
13841386
proptree = self._proptree(filterspec, sortattr)
1385-
proptree.search(search_matches)
1387+
proptree.search(search_matches, retired=retired)
13861388
return proptree.sort()
13871389

13881390
# non-optimized filter_iter, a backend may chose to implement a

test/db_test_base.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2166,6 +2166,27 @@ def testFilteringSortId(self):
21662166
ae(filt(None, {}, ('+','id')),
21672167
['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'])
21682168

2169+
def testFilteringRetiredString(self):
2170+
ae, filter, filter_iter = self.filteringSetup()
2171+
self.db.issue.retire('1')
2172+
self.db.commit()
2173+
r = { None: (['1'], ['1'], ['1'], ['1', '2', '3'], [])
2174+
, True: (['1'], ['1'], ['1'], ['1'], [])
2175+
, False: ([], [], [], ['2', '3'], [])
2176+
}
2177+
for filt in filter, filter_iter:
2178+
for retire in True, False, None:
2179+
ae(filt(None, {'title': ['one']}, ('+','id'),
2180+
retired=retire), r[retire][0])
2181+
ae(filt(None, {'title': ['issue one']}, ('+','id'),
2182+
retired=retire), r[retire][1])
2183+
ae(filt(None, {'title': ['issue', 'one']}, ('+','id'),
2184+
retired=retire), r[retire][2])
2185+
ae(filt(None, {'title': ['issue']}, ('+','id'),
2186+
retired=retire), r[retire][3])
2187+
ae(filt(None, {'title': ['one', 'two']}, ('+','id'),
2188+
retired=retire), r[retire][4])
2189+
21692190
# XXX add sorting tests for other types
21702191

21712192
# nuke and re-create db for restore

0 commit comments

Comments
 (0)