def test_filter_by_tags_and(self): """Show only commrec with correct tags in 'and' configuration.""" ds = CommRecordsDataSource() recs = ds.run_unaggregated( self.company, CommRecordsFilter(tags=AndGroupFilter([ OrGroupFilter([MatchFilter('EaSt')]), OrGroupFilter([MatchFilter('wEsT')]) ])), []) subjects = {r['subject'] for r in recs} expected = set() self.assertEqual(expected, subjects) # Now try adding another tag. self.record_1.tags.add(self.west_tag) self.record_1.save() recs = ds.run_unaggregated( self.company, CommRecordsFilter(tags=AndGroupFilter([ OrGroupFilter([MatchFilter('EaSt')]), OrGroupFilter([MatchFilter('wEsT')]) ])), []) subjects = {r['subject'] for r in recs} expected = {self.record_1.subject} self.assertEqual(expected, subjects)
def test_filter_by_tags_and(self): """ Show only contact with correct tags in 'and' configuration. """ ds = ContactsDataSource() recs = ds.run_unaggregated( self.company, ContactsFilter(tags=AndGroupFilter([ OrGroupFilter([MatchFilter('EaSt')]), OrGroupFilter([MatchFilter('wEsT')]) ])), []) names = {r['name'] for r in recs} expected = set() self.assertEqual(expected, names) # Now try adding another tag. self.john.tags.add(self.west_tag) recs = ds.run_unaggregated( self.company, ContactsFilter(tags=AndGroupFilter([ OrGroupFilter([MatchFilter('EaSt')]), OrGroupFilter([MatchFilter('wEsT')]) ])), []) names = {r['name'] for r in recs} expected = {self.john.name} self.assertEqual(expected, names)
def test_tag_filter(self): """Test that tag filter is built properly.""" result = self.driver.build_filter('{"tags": [[1, 2], [3, 4]]}') self.assertEquals( ContactsFilter(tags=AndGroupFilter([ OrGroupFilter([MatchFilter(1), MatchFilter(2)]), OrGroupFilter([MatchFilter(3), MatchFilter(4)]), ])), result)
def test_clone_without_full(self): """Cloning should remove certain fields.""" filter = PartnersFilter(tags=AndGroupFilter( [OrGroupFilter([MatchFilter('C')])]), locations=CompositeAndFilter({ 'city': MatchFilter('A'), 'state': MatchFilter('B') })) expected_with_city = PartnersFilter( tags=AndGroupFilter([OrGroupFilter([MatchFilter('C')])]), locations=CompositeAndFilter({'city': MatchFilter('A')})) expected_with_state = PartnersFilter( tags=AndGroupFilter([OrGroupFilter([MatchFilter('C')])]), locations=CompositeAndFilter({'state': MatchFilter('B')})) self.assertEqual(expected_with_state, filter.clone_without_city()) self.assertEqual(expected_with_city, filter.clone_without_state())
def test_filter_by_tags_or(self): """Show only partner with correct tags in 'or' configuration.""" ds = PartnersDataSource() recs = ds.run_unaggregated( self.company, PartnersFilter(tags=AndGroupFilter( [OrGroupFilter([MatchFilter('EaSt'), MatchFilter('wEsT')])])), []) names = {r['name'] for r in recs} expected = {self.partner_a.name, self.partner_b.name} self.assertEqual(expected, names)
def test_plain_filter_and(self): """Convert AndGroupFilter to plain object.""" filt = ContactsFilter(tags=AndGroupFilter([ OrGroupFilter([ MatchFilter(1), MatchFilter(2), ]), OrGroupFilter([ MatchFilter(3), MatchFilter(4), ]) ])) self.assertEqual({'tags': [[1, 2], [3, 4]]}, plain_filter(filt))
def test_filter_by_partner_tags(self): """ Test that we can filter by partner tags. """ ds = ContactsDataSource() recs = ds.run_unaggregated( self.company, ContactsFilter(partner_tags=AndGroupFilter( [OrGroupFilter([MatchFilter('rigHt')])])), []) subjects = {r['name'] for r in recs} expected = {self.sue.name} self.assertEqual(expected, subjects)
def test_filter_by_contact_tags(self): """ Test that we can filter by contact tags. """ ds = CommRecordsDataSource() recs = ds.run_unaggregated( self.company, CommRecordsFilter(contact_tags=AndGroupFilter( [OrGroupFilter([MatchFilter('sOuTh')])])), []) subjects = {r['subject'] for r in recs} expected = {self.record_3.subject} self.assertEqual(expected, subjects)
def test_run_count_comm_rec_per_month_no_partners(self): """Trip over a bug in the mysql client driver.""" for (subject, itx) in enumerate(['a', 'b', 'c']): for month in [2, 3, 4]: self.sue.contactrecord_set.add( ContactRecordFactory(subject=subject, date_time=datetime(2015, month, 1))) ds = PartnersDataSource() partners_filter = PartnersFilter( tags=AndGroupFilter([OrGroupFilter([MatchFilter('zzz')])])) recs = ds.run_count_comm_rec_per_month(self.company, partners_filter, ['name', 'year', '-month']) self.assertEqual(0, len(recs))
def test_filter_by_tags(self): """ Should show only contact with correct tags. """ ds = ContactsDataSource() recs = ds.run_unaggregated( self.company, ContactsFilter( tags=AndGroupFilter([OrGroupFilter([MatchFilter('EaSt')])])), []) names = {r['name'] for r in recs} expected = {self.john.name} self.assertEqual(expected, names)
def test_run_count_comm_rec_per_month_empty_partner(self): """One partner, no communication records.""" ds = PartnersDataSource() partners_filter = PartnersFilter( tags=AndGroupFilter([OrGroupFilter([MatchFilter('east')])])) recs = ds.run_count_comm_rec_per_month(self.company, partners_filter, ['name', 'year', '-month']) data = [(r['name'], r['year'], r['month'], r['comm_rec_count']) for r in recs] self.assertEqual(12, len(data)) default_year = datetime.now().year for item in data: self.assertEqual(default_year, item[1]) self.assertEqual(0, item[3])
def test_filter_by_tags(self): """ Show only commrec with correct tags. """ ds = CommRecordsDataSource() recs = ds.run_unaggregated( self.company, CommRecordsFilter( tags=AndGroupFilter([OrGroupFilter([MatchFilter('EaSt')])])), []) subjects = {r['subject'] for r in recs} expected = {self.record_1.subject, self.record_2.subject} self.assertEqual(expected, subjects)
def test_and_group(self): """Test adorning an AndGroupFilter.""" self.maxDiff = 10000 result = adorn_filter( None, self.ds, ContactsFilter(tags=AndGroupFilter([ OrGroupFilter([ MatchFilter('a'), MatchFilter('c'), ]), OrGroupFilter([ MatchFilter('b'), MatchFilter('d'), ]), ]))) self.assertEqual([{ 'tags': ['a', 'c', 'b', 'd'], }], self.ds.adorn_calls) self.assertEqual( ContactsFilter(tags=AndGroupFilter([ OrGroupFilter([ MatchFilter({ 'value': 'a', 'display': 'A', 'hexcolor': 'aaaaaa' }), MatchFilter('c') ]), OrGroupFilter([ MatchFilter({ 'value': 'b', 'display': 'B', 'hexcolor': 'bbbbbb' }), MatchFilter('d') ]) ])), result)
def test_and_group(self): """And group should result in a series of comparisons.""" qs = MockQuerySet() result = apply_filter_to_queryset( qs, AndGroupFilter([ OrGroupFilter([MatchFilter('f')]), OrGroupFilter([MatchFilter('g'), MatchFilter('h')]), MatchFilter('i') ]), 'z') self.assert_filters_equals([ Q(z='f'), Q(z='g') | Q(z='h'), Q(z='i'), ], result.filters)
def test_run_count_comm_rec_per_month_one_partner(self): """Trip over a bug in the mysql client driver.""" for (subject, itx) in enumerate(['a', 'b', 'c']): for year in [2013, 2015, 2014]: for month in [2, 3, 4]: self.sue.contactrecord_set.add( ContactRecordFactory(subject=subject, date_time=datetime( year, month, 1))) ds = PartnersDataSource() partners_filter = PartnersFilter( tags=AndGroupFilter([OrGroupFilter([MatchFilter('west')])])) recs = ds.run_count_comm_rec_per_month(self.company, partners_filter, ['name', 'year', '-month']) data = [(r['name'], r['year'], r['month'], r['comm_rec_count']) for r in recs] self.assertEqual(36, len(data))
def build_filter(self, filter_json): """ Build a filter for the given filter_json filters look like: { filter_column1: some filter_spec..., filter_column2: another filter_spec..., } filter_specs can be any of: missing/null/[]: Empty lists, nulls, or missing keys are all interpreted as do not filter on this column. [date, date]: A list of two dates is date range. The filter class must have a key type of 'date'. 1/"a": A single choice. [1, 2, 3]: A list of choices is an "or group". Match any of the choices. [[1, 2, 3], [4, 5, 6]]: A list of lists of choices is an "and group". Must match any of the first AND any of each of the subsequent groups. {'field1': some filter}: Match each field with the filter given: A CompositeAndFilter. The filter class must have a key type of 'composite'. {'nolink': True}: A special object which means to find objects not linked to the objects in this column. i.e. If this is a tags column, find untagged objects. """ kwargs = {} filter_spec = json.loads(filter_json) filter_type = self.ds.filter_type() types = filter_type.filter_key_types() for key, data in filter_spec.iteritems(): key_type = types.get(key, None) if key_type is None: # empty lists are the same as no filter if data == []: continue elif (isinstance(data, list) and len(data) > 0 and isinstance(data[0], list)): kwargs[key] = AndGroupFilter([ OrGroupFilter([ MatchFilter(v) for v in or_f ]) for or_f in data]) elif isinstance(data, list) and len(data) > 0: kwargs[key] = OrGroupFilter([ MatchFilter(v) for v in data ]) elif isinstance(data, dict) and 'nolink' in data: kwargs[key] = UnlinkedFilter() else: kwargs[key] = MatchFilter(data) elif key_type == 'date_range': date_strings = filter_spec.get(key, None) dates = [ (datetime.strptime(d, "%m/%d/%Y") if d else None) for d in date_strings] kwargs[key] = DateRangeFilter(dates) elif key_type == 'composite': value_map = { col: MatchFilter(value) for col, value in filter_spec.get(key, {}).iteritems() } kwargs[key] = CompositeAndFilter(value_map) else: message = 'DataSource %s has unknown filter key type %s' % ( self.ds.__class__.__name__, repr(key_type)) raise KeyError(message) return filter_type(**kwargs)
def test_and_group_empty(self): """Empty And group should result in no comparisons.""" qs = MockQuerySet() result = apply_filter_to_queryset(qs, AndGroupFilter([]), 'z') self.assert_filters_equals([], result.filters)