Skip to content

Commit f2dc1b1

Browse files
committed
Support use of duplicate rest filters keys. So URL's like:
issues?title=foo&title=bar will find titles with the words foo and bar but not just foo and not just bar. Url like: issues?status=open,resolved&status=closed will find any issue with open, closed or resolved status. Original code would only use the last title or status filter erasing the earlier one.
1 parent d82348d commit f2dc1b1

File tree

2 files changed

+106
-5
lines changed

2 files changed

+106
-5
lines changed

roundup/rest.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,10 @@ def get_collection(self, class_name, input):
681681
):
682682
continue
683683
if isinstance (prop, (hyperdb.Link, hyperdb.Multilink)):
684-
vals = []
684+
if key in filter_props:
685+
vals = filter_props[key]
686+
else:
687+
vals = []
685688
linkcls = self.db.getclass (prop.classname)
686689
for p in value.split(","):
687690
if prop.try_id_parsing and p.isdigit():
@@ -690,7 +693,13 @@ def get_collection(self, class_name, input):
690693
vals.append(linkcls.lookup(p))
691694
filter_props[key] = vals
692695
else:
693-
filter_props[key] = value
696+
if key in filter_props:
697+
if isinstance(filter_props[key], list):
698+
filter_props[key].append(value)
699+
else:
700+
filter_props[key]=[filter_props[key],value]
701+
else:
702+
filter_props[key] = value
694703
if not filter_props:
695704
obj_list = class_obj.list()
696705
else:

test/rest_common.py

Lines changed: 95 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -458,17 +458,17 @@ def testFilter(self):
458458
priority=self.db.priority.lookup('normal')
459459
)
460460
issue_open_norm = self.db.issue.create(
461-
title='foo2',
461+
title='foo2 normal',
462462
status=self.db.status.lookup('open'),
463463
priority=self.db.priority.lookup('normal')
464464
)
465465
issue_closed_norm = self.db.issue.create(
466-
title='foo3',
466+
title='foo3 closed normal',
467467
status=self.db.status.lookup('closed'),
468468
priority=self.db.priority.lookup('normal')
469469
)
470470
issue_closed_crit = self.db.issue.create(
471-
title='foo4',
471+
title='foo4 closed',
472472
status=self.db.status.lookup('closed'),
473473
priority=self.db.priority.lookup('critical')
474474
)
@@ -529,6 +529,98 @@ def testFilter(self):
529529
self.assertNotIn(get_obj(base_path, issue_open_norm),
530530
results['data']['collection'])
531531

532+
# Retrieve all issue status=closed and priority=normal,critical
533+
# using duplicate priority key's.
534+
form = cgi.FieldStorage()
535+
form.list = [
536+
cgi.MiniFieldStorage('status', 'closed'),
537+
cgi.MiniFieldStorage('priority', 'normal'),
538+
cgi.MiniFieldStorage('priority', 'critical')
539+
]
540+
results = self.server.get_collection('issue', form)
541+
self.assertEqual(self.dummy_client.response_code, 200)
542+
self.assertIn(get_obj(base_path, issue_closed_crit),
543+
results['data']['collection'])
544+
self.assertIn(get_obj(base_path, issue_closed_norm),
545+
results['data']['collection'])
546+
self.assertNotIn(get_obj(base_path, issue_open_crit),
547+
results['data']['collection'])
548+
self.assertNotIn(get_obj(base_path, issue_open_norm),
549+
results['data']['collection'])
550+
551+
# Retrieve all issues with title containing
552+
# closed, normal and 3 using duplicate title filterkeys
553+
form = cgi.FieldStorage()
554+
form.list = [
555+
cgi.MiniFieldStorage('title', 'closed'),
556+
cgi.MiniFieldStorage('title', 'normal'),
557+
cgi.MiniFieldStorage('title', '3')
558+
]
559+
results = self.server.get_collection('issue', form)
560+
self.assertEqual(self.dummy_client.response_code, 200)
561+
self.assertNotIn(get_obj(base_path, issue_closed_crit),
562+
results['data']['collection'])
563+
self.assertIn(get_obj(base_path, issue_closed_norm),
564+
results['data']['collection'])
565+
self.assertNotIn(get_obj(base_path, issue_open_crit),
566+
results['data']['collection'])
567+
self.assertNotIn(get_obj(base_path, issue_open_norm),
568+
results['data']['collection'])
569+
self.assertEqual(len(results['data']['collection']), 1)
570+
571+
# Retrieve all issues (no hits) with title containing
572+
# closed, normal and foo3 in this order using title filter
573+
form = cgi.FieldStorage()
574+
form.list = [
575+
cgi.MiniFieldStorage('title', 'closed normal foo3')
576+
]
577+
results = self.server.get_collection('issue', form)
578+
self.assertEqual(self.dummy_client.response_code, 200)
579+
self.assertNotIn(get_obj(base_path, issue_closed_crit),
580+
results['data']['collection'])
581+
self.assertNotIn(get_obj(base_path, issue_closed_norm),
582+
results['data']['collection'])
583+
self.assertNotIn(get_obj(base_path, issue_open_crit),
584+
results['data']['collection'])
585+
self.assertNotIn(get_obj(base_path, issue_open_norm),
586+
results['data']['collection'])
587+
self.assertEqual(len(results['data']['collection']), 0)
588+
589+
# Retrieve all issues with title containing
590+
# foo3, closed and normal in this order using title filter
591+
form = cgi.FieldStorage()
592+
form.list = [
593+
cgi.MiniFieldStorage('title', 'foo3 closed normal')
594+
]
595+
results = self.server.get_collection('issue', form)
596+
self.assertEqual(self.dummy_client.response_code, 200)
597+
self.assertNotIn(get_obj(base_path, issue_closed_crit),
598+
results['data']['collection'])
599+
self.assertIn(get_obj(base_path, issue_closed_norm),
600+
results['data']['collection'])
601+
self.assertNotIn(get_obj(base_path, issue_open_crit),
602+
results['data']['collection'])
603+
self.assertNotIn(get_obj(base_path, issue_open_norm),
604+
results['data']['collection'])
605+
self.assertEqual(len(results['data']['collection']), 1)
606+
607+
# Retrieve all issues with word closed in title
608+
form = cgi.FieldStorage()
609+
form.list = [
610+
cgi.MiniFieldStorage('title', 'closed'),
611+
]
612+
results = self.server.get_collection('issue', form)
613+
self.assertEqual(self.dummy_client.response_code, 200)
614+
self.assertIn(get_obj(base_path, issue_closed_crit),
615+
results['data']['collection'])
616+
self.assertIn(get_obj(base_path, issue_closed_norm),
617+
results['data']['collection'])
618+
self.assertNotIn(get_obj(base_path, issue_open_crit),
619+
results['data']['collection'])
620+
self.assertNotIn(get_obj(base_path, issue_open_norm),
621+
results['data']['collection'])
622+
self.assertEqual(len(results['data']['collection']), 2)
623+
532624
def testPagination(self):
533625
"""
534626
Test pagination. page_size is required and is an integer

0 commit comments

Comments
 (0)