def test(self): operator = getattr(op, '_python_operator', op) query = these(parent for parent in this('p') if operator(parent.age, parent.check, parent.names)) expected = operator(this('p').age, this('p').check, this('p').names) self.assertIs(1, len(query.filters)) with context(UNPROXIFING_CONTEXT): self.assertEqual(expected, query.filters[0])
def test_complex_query_with_3_tokens(self): query = these((parent.title + parent.name, child.name + child.nick, toy.name) for parent in this('parent') if parent.children for child in parent.children if child.toys for toy in child.toys if (parent.age > 32) & (child.age < 5) | (toy.type == 'laptop')) p = this('parent') c = p.children t = c.toys filters = query.filters expected_filters = [((p.age > 32) & (c.age < 5) | (t.type == 'laptop')), p.children, c.toys] tokens = query.tokens expected_tokens = [p, c, t] selection = query.selection expected_selection = (p.title + p.name, c.name + c.nick, t.name) with context(UNPROXIFING_CONTEXT): self.assertEqual(selection, expected_selection) self.assertEqual(len(expected_filters), len(filters)) for f in expected_filters: self.assertIn(f, filters) self.assertEqual(len(expected_tokens), len(tokens)) for t in expected_tokens: self.assertIn(t, tokens)
def test_complex_query_with_3_tokens(self): query = these( (parent.title + parent.name, child.name + child.nick, toy.name) for parent in this('parent') if parent.children for child in parent.children if child.toys for toy in child.toys if (parent.age > 32) & (child.age < 5) | (toy.type == 'laptop')) p = this('parent') c = p.children t = c.toys filters = query.filters expected_filters = [ ((p.age > 32) & (c.age < 5) | (t.type == 'laptop')), p.children, c.toys ] tokens = query.tokens expected_tokens = [p, c, t] selection = query.selection expected_selection = (p.title + p.name, c.name + c.nick, t.name) with context(UNPROXIFING_CONTEXT): self.assertEqual(selection, expected_selection) self.assertEqual(len(expected_filters), len(filters)) for f in expected_filters: self.assertIn(f, filters) self.assertEqual(len(expected_tokens), len(tokens)) for t in expected_tokens: self.assertIn(t, tokens)
def test_complex_query_with_3_tokens(): query = these((parent.title + parent.name, child.name + child.nick, toy.name) for parent in this('parent') if parent.children for child in parent.children if child.toys for toy in child.toys if (parent.age > 32) & (child.age < 5) | (toy.type == 'laptop')) p = this('parent') c = p.children t = c.toys filters = query.filters expected_filters = [((p.age > 32) & (c.age < 5) | (t.type == 'laptop')), p.children, c.toys] tokens = [tk.expression for tk in query.tokens] expected_tokens = [p, c, t] selection = query.selection expected_selection = (p.title + p.name, c.name + c.nick, t.name) with context(UNPROXIFING_CONTEXT): assert selection == expected_selection assert len(expected_filters) == len(filters) for f in expected_filters: assert f in filters assert len(expected_tokens) == len(tokens) for t in expected_tokens: assert t in tokens
def test_20121022_complex_intermingled_query(self): ''' Tests that toy.type == 'laptop' does not get singled out of its containing expression. The following procedure is not current any more; but we leave it there for historical reasons. Since the introduction of "particle bubble" that captures all the parts and tokens, we have removed the :attr:`xotl.ql.interfaces.IQueryPart.tokens`. Slight variation over the same test of previous testcase but that shows how `|` that if we don't have the `tokens` params things will go wrong: - `parent.age > 32` will have `this('parent')` as its token - `child.age < 5` will have `this('parent').children` as its token. - When building `(parent.age > 32) & (child.age < 5)` the resultant part will have only `this('parent')` as the token, and - `contains(child.toys, 'laptop')` will be attached to `this('parent').children`, but this will create a stack in the token for `child`, the stack will contain: ``child.age < 5``, and ``contains(child.toys, 'laptop')``, for they don't merge. - Then, building ``... | contains(child.toys, 'laptop')`` will be attached to `this('parent')` only! This will cause that the token `this('parent').children` will be left with a stack of two items that will be considered separate filters, which is wrong! The solutions seems to be simply to make `this('parent').children` aware of parts that are generated. So :attr:`xotl.ql.core.QuerPart.tokens` is born. ''' parent, child, toy = next((parent.title + parent.name, child.name + child.nick, toy.name) for parent in this('parent') for child in parent.children for toy in child.toys if (parent.age > 32) & (child.age < 5) | (toy.type == 'laptop')) parts = self.bubble.parts parent = this('parent') child = parent.children ok = lambda x: self.assertEquals(str(x), str(parts.pop(-1))) toy = child.toys ok(toy.name) ok(child.name + child.nick) ok(parent.title + parent.name) ok((parent.age > 32) & (child.age < 5) | (toy.type == 'laptop')) with self.assertRaises(IndexError): print(ok(None))
def test_free_terms_are_not_captured(self): from xotl.ql.expressions import any_ next(parent for parent in this('parent') if parent.name if any_(this.children, this.age < 6)) parts = self.bubble.parts self.assertIs(1, len(parts)) pname = this('parent').name with context(UNPROXIFING_CONTEXT): self.assertIn(pname, parts)
def test_20121022_complex_intermingled_query(self): ''' Tests that toy.type == 'laptop' does not get singled out of its containing expression. The following procedure is not current any more; but we leave it there for historical reasons. Since the introduction of "particle bubble" that captures all the parts and tokens, we have removed the :attr:`xotl.ql.interfaces.IQueryPart.tokens`. Slight variation over the same test of previous testcase but that shows how `|` that if we don't have the `tokens` params things will go wrong: - `parent.age > 32` will have `this('parent')` as its token - `child.age < 5` will have `this('parent').children` as its token. - When building `(parent.age > 32) & (child.age < 5)` the resultant part will have only `this('parent')` as the token, and - `contains(child.toys, 'laptop')` will be attached to `this('parent').children`, but this will create a stack in the token for `child`, the stack will contain: ``child.age < 5``, and ``contains(child.toys, 'laptop')``, for they don't merge. - Then, building ``... | contains(child.toys, 'laptop')`` will be attached to `this('parent')` only! This will cause that the token `this('parent').children` will be left with a stack of two items that will be considered separate filters, which is wrong! The solutions seems to be simply to make `this('parent').children` aware of parts that are generated. So :attr:`xotl.ql.core.QuerPart.tokens` is born. ''' parent, child, toy = next( (parent.title + parent.name, child.name + child.nick, toy.name) for parent in this('parent') for child in parent.children for toy in child.toys if (parent.age > 32) & (child.age < 5) | (toy.type == 'laptop')) parts = self.bubble.parts parent = this('parent') child = parent.children ok = lambda x: self.assertEquals(str(x), str(parts.pop(-1))) toy = child.toys ok(toy.name) ok(child.name + child.nick) ok(parent.title + parent.name) ok((parent.age > 32) & (child.age < 5) | (toy.type == 'laptop')) with self.assertRaises(IndexError): print(ok(None))
def test_plain_iter(): with bubbling(): t1 = next(iter(this)) with context(UNPROXIFING_CONTEXT): assert IBoundTerm.providedBy(t1) t1 = next(parent for parent in this('parent')) assert 'parent' == unboxed(t1).name t1 = next(parent for parent in this('parent').children) assert 'children' == unboxed(t1).name
def test_is_a_partnership_is_not_forgotten(self): from itertools import izip query = these( (person, partner) for person, partner in izip(this('person'), this('partner')) for rel in this('relation') if rel.type == 'partnership' if (rel.subject == person) & (rel.object == partner)) filters = list(query.filters) expected_rel_type = this('relation').type == 'partnership' with context(UNPROXIFING_CONTEXT): self.assertIn(expected_rel_type, filters) self.assertIs(2, len(filters))
def test_is_a_partnership_is_not_forgotten(self): from itertools import izip query = these((person, partner) for person, partner in izip(this('person'), this('partner')) for rel in this('relation') if rel.type == 'partnership' if (rel.subject == person) & (rel.object == partner)) filters = list(query.filters) expected_rel_type = this('relation').type == 'partnership' with context(UNPROXIFING_CONTEXT): self.assertIn(expected_rel_type, filters) self.assertIs(2, len(filters))
def test_is_a_partnership_is_not_forgotten(): from xoutil.iterators import zip query = these((person, partner) for person, partner in zip(this('person'), this('partner')) for rel in this('relation') if rel.type == 'partnership' if (rel.subject == person) & (rel.object == partner)) filters = list(query.filters) expected_rel_type = this('relation').type == 'partnership' with context(UNPROXIFING_CONTEXT): assert expected_rel_type in filters assert len(filters) == 2
def test_basic_queries(self): from xotl.ql.expressions import count query = these((parent.title + parent.name, count(child.toys)) for parent in this('parent') if parent.age < 40 for child in parent.children if child.age > 5) self.assertTrue(provides_any(query, IQueryObject)) (parent_full_name, child_toys) = query.selection full_name_expectation = this('parent').title + this('parent').name # child_name_expectation = this('parent').children.name child_toys_expectation = count(this('parent').children.toys) parent_age_test = this('parent').age < 40 children_age_test = this('parent').children.age > 5 parent_token = this('parent') children_token = this('parent').children with context(UNPROXIFING_CONTEXT): self.assertEqual(parent_full_name, full_name_expectation) # self.assertEqual(child_name, child_name_expectation) self.assertEqual(child_toys, child_toys_expectation) filters = query.filters self.assertEqual(2, len(filters)) self.assertIn(parent_age_test, filters) self.assertIn(children_age_test, filters) tokens = query.tokens self.assertEqual(2, len(tokens)) self.assertIn(parent_token, tokens) self.assertIn(children_token, tokens)
def test_basic_queries(): from xotl.ql.expressions import count query = these((parent.title + parent.name, count(child.toys)) for parent in this('parent') if parent.age < 40 for child in parent.children if child.age > 5) assert provides_any(query, IQueryObject) (parent_full_name, child_toys) = query.selection full_name_expectation = this('parent').title + this('parent').name child_toys_expectation = count(this('parent').children.toys) parent_age_test = this('parent').age < 40 children_age_test = this('parent').children.age > 5 parent_token = this('parent') children_token = this('parent').children with context(UNPROXIFING_CONTEXT): assert parent_full_name == full_name_expectation assert child_toys == child_toys_expectation filters = query.filters assert len(filters) == 2 assert parent_age_test in filters assert children_age_test in filters tokens = [tk.expression for tk in query.tokens] assert len(tokens) == 2 assert parent_token in tokens assert children_token in tokens
def test_yield_once_per_query(self): q = (a for c in this for b in c.bs for a in b.a) self.assertIsNotNone(next(q)) with self.assertRaises(StopIteration): next(q) # TODO: Document how to obtain the queries qs = (a for i in range(3) for b in this('b' + str(i)) for a in b.a) for i in range(3): expected = this('b' + str(i)).a returned = unboxed(next(qs)).expression with context(UNPROXIFING_CONTEXT): self.assertEqual(expected, returned) with self.assertRaises(StopIteration): next(qs)
def test_yield_once_per_query(): q = (a for c in this for b in c.bs for a in b.a) assert next(q) is not None with pytest.raises(StopIteration): next(q) # TODO: Document how to obtain the queries qs = (a for i in range(3) for b in this('b' + str(i)) for a in b.a) for i in range(3): expected = this('b' + str(i)).a returned = next(qs) with context(UNPROXIFING_CONTEXT): assert expected == returned with pytest.raises(StopIteration): next(qs)
def test_complex_query_building(self): parent, child = next( (parent.title + parent.name, child.name + child.nick) for parent in this('parent') if (parent.age > 32) & parent.children for child in parent.children if child.age < 5) ok = self.assertEquals parts = self.bubble.parts parent = this('parent') child = parent.children ok(str(child.name + child.nick), str(parts[-1])) ok(str(parent.title + parent.name), str(parts[-2])) ok(str(child.age < 5), str(parts[-3])) ok(str((parent.age > 32) & parent.children), str(parts[-4])) with self.assertRaises(IndexError): print(str(parts[-5]))
def test_free_terms_are_not_captured(self): from xotl.ql.expressions import any_ these(parent for parent in this('parent') if parent.name if any_(this.children, this.age < 6)) parts = self.bubble.parts self.assertIs(0, len(parts))
def test_plain_iter(self): t1 = next(iter(this)) with context(UNPROXIFING_CONTEXT): self.assertTrue(IQueryPart.providedBy(t1), 'When itering over a this instance we ' 'should get an IQueryPart object') t1 = next(parent for parent in this('parent')) self.assertEquals('parent', unboxed(unboxed(t1)._expression).name, 'The name of the QueryBuilderToken should be ' 'the same as the name of the actual instance') t1 = next(parent for parent in this('parent').children) self.assertEquals('children', unboxed(unboxed(t1)._expression).name, 'The name of the QueryBuilderToken should be ' 'the same as the name of the actual instance')
def test_undetected_particles(self): from xotl.ql.expressions import any_ next(parent for parent in this('parent') if any_(child for child in parent.children if child.age < 6)) parts = self.bubble.parts self.assertIs(0, len(parts))
def test_free_terms_are_not_captured(): from xotl.ql.expressions import any_ with bubbling() as current: next(parent for parent in this('parent') if parent.name if any_(this.children, this.age < 6)) parts = current.bubble.parts assert len(parts) == 2 pname = this('parent').name expected = any_(this.children, this.age < 6) with context(UNPROXIFING_CONTEXT): assert pname in parts assert expected in parts
def test_complex_query_building(self): parent, child = next((parent.title + parent.name, child.name + child.nick) for parent in this('parent') if (parent.age > 32) & parent.children for child in parent.children if child.age < 5) ok = self.assertEquals parts = self.bubble.parts parent = this('parent') child = parent.children ok(str(child.name + child.nick), str(parts[-1])) ok(str(parent.title + parent.name), str(parts[-2])) ok(str(child.age < 5), str(parts[-3])) ok(str((parent.age > 32) & parent.children), str(parts[-4])) with self.assertRaises(IndexError): print(str(parts[-5]))
def test_most_basic_query(self): query = these(parent for parent in this('parent') if parent.age > 40) self.assertTrue(provides_any(query, IQueryObject)) (p, ) = query.selection token_expectation = p_expected = this('parent') filter_expectation = this('parent').age > 40 with context(UNPROXIFING_CONTEXT): self.assertEqual(p, p_expected) filters = query.filters self.assertEqual(1, len(filters)) self.assertIn(filter_expectation, filters) tokens = query.tokens self.assertEqual(1, len(tokens)) self.assertIn(token_expectation, tuple(tokens))
def test_right_bindings(): with bubbling() as current: next((parent, child) for parent in this('parent') if parent.children.updated_since(days=1) for child in parent.children if child.age < 4) # The query has two filters: # # this('parent').children & (count(this('parent').children) > 4) # this('parent').children.age < 5 # # If we regard every term `this('parent').children` as the *token*, # what would be the meaning of the first condition? How do we # distinguish from conditions over the named-token and the expression # that generates the token? i.e in `for child in parent.children`, the # `child` token is *not* the same as the term `parent.children`. # # Now the token of the relevant query might help, but then the machine # should not strip those tokens from query-parts. parts = current.bubble.parts bubble_tokens = current.bubble.tokens assert len(parts) == 2 with context(UNPROXIFING_CONTEXT): parent_token = next((token for token in bubble_tokens if token.expression == this('parent')), None) children_token = next((token for token in bubble_tokens if token.expression != this('parent')), None) child_age_filter = parts.pop(-1) parent_children_updated_filter = parts.pop(-1) with pytest.raises(IndexError): parts.pop(-1) with context(UNPROXIFING_CONTEXT): child_age_term = child_age_filter.children[0] assert child_age_term.binding == children_token # Note that: parent.children.updated_since(days=1) # is equivalent to invoke(parent.children.updated_since, days=1) parent_children_term = parent_children_updated_filter.children[0] assert parent_children_term.binding == parent_token assert dict(days=1) == parent_children_updated_filter.named_children
def test_complex_query_building_with_dict(self): from xotl.ql.expressions import min_, max_ d = {parent.age: (min_(child.age), max_(child.age)) for parent in this('parent') if (parent.age > 32) & parent.children for child in parent.children if child.age < 5} parts = self.bubble.parts ok = lambda which: self.assertEqual(str(which), str(parts.pop(-1))) parent = this('parent') child = parent.children ok(parent.age) # The key of the dict is the top-most expression ok(max_(child.age)) ok(min_(child.age)) ok(child.age < 5) ok((parent.age > 32) & parent.children) with self.assertRaises(IndexError): ok(None)
def test_undetected_particles(): from xotl.ql.expressions import any_ with bubbling() as current: next(parent for parent in this('parent') if any_(child for child in parent.children if child.age < 6)) parts = current.bubble.parts # `child.age < 6` should not be leaked assert 1 == len(parts)
def test_most_basic_query(): query = these(parent for parent in this('parent') if parent.age > 40) assert provides_any(query, IQueryObject) # Since the query selects a single object, a single object must be # placed as the selection (not a tuple!). p = query.selection token_expectation = p_expected = this('parent') filter_expectation = this('parent').age > 40 with context(UNPROXIFING_CONTEXT): assert p == p_expected filters = query.filters assert len(filters) == 1 assert filter_expectation in filters tokens = [tk.expression for tk in query.tokens] assert len(tokens) == 1 assert token_expectation in tuple(tokens)
def test_complex_query_building_with_dict(self): from xotl.ql.expressions import min_, max_ d = { parent.age: (min_(child.age), max_(child.age)) for parent in this('parent') if (parent.age > 32) & parent.children for child in parent.children if child.age < 5 } parts = self.bubble.parts ok = lambda which: self.assertEqual(str(which), str(parts.pop(-1))) parent = this('parent') child = parent.children ok(parent.age) # The key of the dict is the top-most expression ok(max_(child.age)) ok(min_(child.age)) ok(child.age < 5) ok((parent.age > 32) & parent.children) with self.assertRaises(IndexError): ok(None)
def test_complex_query_building(): with bubbling() as current: parent, child = next((parent.title + parent.name, child.name + child.nick) for parent in this('parent') if (parent.age > 32) & parent.children for child in parent.children if child.age < 5) parts = current.bubble.parts assert len(parts) == 4 # 2 filters + 2 selections parent = this('parent') child = parent.children assert str(child.name + child.nick) == str(parts[-1]) assert str(parent.title + parent.name) == str(parts[-2]) assert str(child.age < 5) == str(parts[-3]) assert str((parent.age > 32) & parent.children) == str(parts[-4]) with pytest.raises(IndexError): print(str(parts[-5]))
def test_plain_iter(self): t1 = next(iter(this)) with context(UNPROXIFING_CONTEXT): self.assertTrue( IQueryPart.providedBy(t1), 'When itering over a this instance we ' 'should get an IQueryPart object') t1 = next(parent for parent in this('parent')) self.assertEquals( 'parent', unboxed(unboxed(t1)._expression).name, 'The name of the QueryBuilderToken should be ' 'the same as the name of the actual instance') t1 = next(parent for parent in this('parent').children) self.assertEquals( 'children', unboxed(unboxed(t1)._expression).name, 'The name of the QueryBuilderToken should be ' 'the same as the name of the actual instance')
def test_worst_case_must_have_3_filters_and_3_tokens(): from xoutil.compat import zip with bubbling() as current: next(person for person, partner in zip(this('person'), this('partner')) for rel in this('relation') if rel.type == 'partnership' if rel.subject == person if rel.object == partner if partner.age > 32) parts = current.bubble.parts tokens = current.bubble.tokens assert len(parts) == 4 tokens = [tk.expression for tk in tokens] def ok(x): assert str(x) == str(parts.pop(-1)) person = this('person') partner = this('partner') rel = this('relation') assert person in tokens assert partner in tokens assert rel in tokens ok(partner.age > 32) ok(rel.object == partner) ok(rel.subject == person) ok(rel.type == 'partnership') with pytest.raises(IndexError): ok(None)
def test_is_a_partnership_is_not_forgotten(): from xoutil.compat import zip with bubbling() as current: next((person, partner) for person, partner in zip(this('person'), this('partner')) for rel in this('relation') if rel.type == 'partnership' if (rel.subject == person) & (rel.object == partner)) parts = current.bubble.parts tokens = current.bubble.tokens assert len(parts) == 2 # Only the 2 filters tokens = [tk.expression for tk in tokens] def ok(x): assert str(x) == str(parts.pop(-1)) person = this('person') partner = this('partner') rel = this('relation') assert person in tokens assert partner in tokens assert rel in tokens ok((rel.subject == person) & (rel.object == partner)) ok(rel.type == 'partnership') with pytest.raises(IndexError): ok(None)
def test_worst_case_must_have_3_filters_and_3_tokens(self): from itertools import izip query = these( person for person, partner in izip(this('person'), this('partner')) for rel in this('relation') if rel.type == 'partnership' if rel.subject == person if rel.object == partner if partner.age > 32) filters = list(query.filters) tokens = list(query.tokens) person, partner, rel = this('person'), this('partner'), this( 'relation') expected_rel_type_filter = rel.type == 'partnership' expected_rel_subject_filter = rel.subject == person expected_rel_obj_filter = rel.object == partner expected_partner_age = partner.age > 32 with context(UNPROXIFING_CONTEXT): self.assertIs(4, len(filters)) self.assertIn(expected_rel_type_filter, filters) self.assertIn(expected_rel_subject_filter, filters) self.assertIn(expected_rel_obj_filter, filters) self.assertIn(expected_partner_age, filters) self.assertIn(person, tokens) self.assertIn(rel, tokens) self.assertIs(3, len(tokens)) self.assertIn(partner, tokens)
def test_worst_case_must_have_3_filters_and_3_tokens(self): from itertools import izip next(person for person, partner in izip(this('person'), this('partner')) for rel in this('relation') if rel.type == 'partnership' if rel.subject == person if rel.object == partner if partner.age > 32) parts = self.bubble.parts tokens = self.bubble.tokens ok = lambda x: self.assertEqual(str(x), str(parts.pop(-1))) person = this('person') partner = this('partner') rel = this('relation') self.assertIn(person, tokens) self.assertIn(partner, tokens) self.assertIn(rel, tokens) ok(partner.age > 32) ok(rel.object == partner) ok(rel.subject == person) ok(rel.type == 'partnership') with self.assertRaises(IndexError): ok(None)
def test_worst_case_must_have_3_filters_and_3_tokens(): from xoutil.iterators import zip query = these(person for person, partner in zip(this('person'), this('partner')) for rel in this('relation') if rel.type == 'partnership' if rel.subject == person if rel.object == partner if partner.age > 32) filters = list(query.filters) tokens = [tk.expression for tk in query.tokens] person, partner, rel = this('person'), this('partner'), this('relation') expected_rel_type_filter = rel.type == 'partnership' expected_rel_subject_filter = rel.subject == person expected_rel_obj_filter = rel.object == partner expected_partner_age = partner.age > 32 with context(UNPROXIFING_CONTEXT): assert len(filters) == 4 assert expected_rel_type_filter in filters assert expected_rel_subject_filter in filters assert expected_rel_obj_filter in filters assert expected_partner_age in filters assert len(tokens) == 3 assert person in tokens assert rel in tokens assert partner in tokens
def test_right_bindings(self): next((parent, child) for parent in this('parent') if parent.children.updated_since(days=1) for child in parent.children if child.age < 4) # The query has two filters: # # this('parent').children & (count(this('parent').children) > 4) # this('parent').children.age < 5 # # If we regard every term `this('parent').children` as the *token*, # what would be the meaning of the first condition? How do we # distinguish from conditions over the named-token and the # expression that generates the token? # i.e in `for child in parent.children`, the `child` token # is *not* the same as the term `parent.children`. # # Now the token of the relevant query might help, but then the # machine should not strip those tokens from query-parts. parts = self.bubble.parts bubble_tokens = self.bubble.tokens with context(UNPROXIFING_CONTEXT): parent_token = next((token for token in bubble_tokens if token.expression == this('parent')), None) children_token = next((token for token in bubble_tokens if token.expression != this('parent')), None) child_age_filter = parts.pop(-1) parent_children_updated_filter = parts.pop(-1) with self.assertRaises(IndexError): parts.pop(-1) with context(UNPROXIFING_CONTEXT): child_age_term = child_age_filter.children[0] self.assertEqual(child_age_term.binding, children_token) # Note that: parent.children.updated_since(days=1) # is equivalent to invoke(parent.children.updated_since, days=1) parent_children_term = parent_children_updated_filter.children[0] self.assertEqual(parent_children_term.binding, parent_token) self.assertEqual(dict(days=1), parent_children_updated_filter.named_children)
def test_worst_case_must_have_3_filters_and_3_tokens(self): from itertools import izip query = these(person for person, partner in izip(this('person'), this('partner')) for rel in this('relation') if rel.type == 'partnership' if rel.subject == person if rel.object == partner if partner.age > 32) filters = list(query.filters) tokens = list(query.tokens) person, partner, rel = this('person'), this('partner'), this('relation') expected_rel_type_filter = rel.type == 'partnership' expected_rel_subject_filter = rel.subject == person expected_rel_obj_filter = rel.object == partner expected_partner_age = partner.age > 32 with context(UNPROXIFING_CONTEXT): self.assertIs(4, len(filters)) self.assertIn(expected_rel_type_filter, filters) self.assertIn(expected_rel_subject_filter, filters) self.assertIn(expected_rel_obj_filter, filters) self.assertIn(expected_partner_age, filters) self.assertIn(person, tokens) self.assertIn(rel, tokens) self.assertIs(3, len(tokens)) self.assertIn(partner, tokens)
def test_basic_queries_building(self): ok = self.assertEquals expr = next(parent.title + parent.name for parent in this('parent') if (parent.age > 32) & parent.married & parent.spouse.alive) parts = self.bubble.parts # The select part is at the top ok("this('parent').title + this('parent').name", str(parts[-1])) # Then the binding ok("((this('parent').age > 32) and this('parent').married) and " "this('parent').spouse.alive", str(parts[-2])) with self.assertRaises(IndexError): print(str(parts[-3]))
def test_complex_query_building_with_dict(): from xotl.ql.expressions import min_, max_ with bubbling() as current: d = {parent.age: (min_(child.age), max_(child.age)) for parent in this('parent') if (parent.age > 32) & parent.children for child in parent.children if child.age < 5} parts = current.bubble.parts assert len(parts) == 5 def ok(which): assert str(which) == str(parts.pop(-1)) parent = this('parent') child = parent.children ok(parent.age) # The key of the dict is the top-most expression ok(max_(child.age)) ok(min_(child.age)) ok(child.age < 5) ok((parent.age > 32) & parent.children) with pytest.raises(IndexError): ok(None)
def test_basic_queries_building(self): ok = self.assertEquals expr = next(parent.title + parent.name for parent in this('parent') if (parent.age > 32) & parent.married & parent.spouse.alive) parts = self.bubble.parts # The select part is at the top ok("this('parent').title + this('parent').name", str(parts[-1])) # Then the binding ok( "((this('parent').age > 32) and this('parent').married) and " "this('parent').spouse.alive", str(parts[-2])) with self.assertRaises(IndexError): print(str(parts[-3]))
def test_thesefy_good_meta(self): from xotl.ql.core import thesefy class Meta(type): def __iter__(self): from xoutil.objects import nameof return iter(this(nameof(self))) @thesefy("Person") class Person(object): __metaclass__ = Meta q = these(who for who in Person if who.age > 30) q1 = these(who for who in this('Person') if who.age > 30) with context(UNPROXIFING_CONTEXT): self.assertEqual(q.selection, q1.selection)
def _test_class(self, Person): from xotl.ql.expressions import is_instance q = these((who for who in Person if who.age > 30), limit=100) # We assume that Person has been thesefied with thesefy('Person') who = domain = this('Person') q1 = these(w for w in domain if is_instance(w, Person) if w.age > 30) is_filter = is_instance(who, Person) age_filter = who.age > 30 with context(UNPROXIFING_CONTEXT): self.assertEqual(2, len(q.filters)) self.assertEqual(2, len(q1.filters)) self.assertIn(is_filter, q.filters) self.assertIn(is_filter, q1.filters) self.assertIn(age_filter, q.filters) self.assertIn(age_filter, q1.filters) self.assertEqual(q.selection, q1.selection) self.assertEqual(q.tokens, q1.tokens)
def test_right_bindings(self): these((parent, child) for parent in this('parent') if parent.children.updated_since(days=1) for child in parent.children if child.age < 4) # The query has two filters: # # this('parent').children & (count(this('parent').children) > 4) # this('parent').children.age < 5 # # If we regard every term `this('parent').children` as the *token*, # what would be the meaning of the first condition? How do we # distinguish from conditions over the named-token and the # expression that generates the token? # i.e in `for child in parent.children`, the `child` token # is *not* the same as the term `parent.children`. # # Now the token of the relevant query might help, but then the # machine should not strip those tokens from query-parts. parts = self.bubble.parts self.assertEqual(0, len(parts))
def test_theres_a_token_for_partnership(self): from itertools import izip query = these( (person, partner) for person, partner in izip(this('person'), this('partner')) for rel in this('relation') if rel.type == 'partnership' if (rel.subject == person) & (rel.object == partner)) tokens = list(query.tokens) person, partner, rel = this('person'), this('partner'), this( 'relation') with context(UNPROXIFING_CONTEXT): self.assertIs(3, len(tokens)) self.assertIn(rel, tokens) self.assertIn(person, tokens) self.assertIn(partner, tokens)
def test_is_a_partnership_is_not_forgotten(self): from itertools import izip next((person, partner) for person, partner in izip(this('person'), this('partner')) for rel in this('relation') if rel.type == 'partnership' if (rel.subject == person) & (rel.object == partner)) parts = self.bubble.parts tokens = self.bubble.tokens ok = lambda x: self.assertEqual(str(x), str(parts.pop(-1))) person = this('person') partner = this('partner') rel = this('relation') self.assertIn(person, tokens) self.assertIn(partner, tokens) self.assertIn(rel, tokens) ok((rel.subject == person) & (rel.object == partner)) ok(rel.type == 'partnership') with self.assertRaises(IndexError): ok(None)
def __iter__(self): from xoutil.objects import nameof return iter(this(nameof(self)))