Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds tests for filtering/sorting hybrid properties #621

Merged
merged 1 commit into from
Feb 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions tests/test_fetching.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@

from sqlalchemy import Column
from sqlalchemy import ForeignKey
from sqlalchemy import func
from sqlalchemy import Integer
from sqlalchemy import select
from sqlalchemy import Unicode
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import backref
from sqlalchemy.orm import relationship

Expand Down Expand Up @@ -54,15 +57,33 @@ class Person(self.Base):
age = Column(Integer)
name = Column(Unicode)

@hybrid_property
def is_minor(self):
if not hasattr(self, 'age') or self.age is None:
return False
return self.age <= 18

class Article(self.Base):
__tablename__ = 'article'
id = Column(Integer, primary_key=True)
author_id = Column(Integer, ForeignKey('person.id'))
author = relationship('Person', backref=backref('articles'))
comments = relationship('Comment')

@hybrid_property
def num_comments(self):
return len(self.comments)

@num_comments.expression
def num_comments(cls):
return select([func.count(self.Comment.id)]).\
where(self.Comment.article_id == cls.id).\
label('numcomments')

class Comment(self.Base):
__tablename__ = 'comment'
id = Column(Integer, primary_key=True)
article_id = Column(Integer, ForeignKey(Article.id))

@classmethod
def query(cls):
Expand Down Expand Up @@ -302,6 +323,50 @@ def test_sorting_null_field(self):
# TODO In Python 2.7 or later, this should be a set literal.
assert set(['1', '4']) == set(person_ids[:2])

def test_sorting_hybrid_property(self):
"""Test for sorting on a hybrid property."""
person1 = self.Person(id=1, age=10)
person2 = self.Person(id=2, age=20)
self.session.add_all([person1, person2])
self.session.commit()

query_string = {'sort': 'is_minor'}
response = self.app.get('/api/person', query_string=query_string)
document = loads(response.data)
people = document['data']
self.assertEqual(['2', '1'], list(map(itemgetter('id'), people)))

query_string = {'sort': '-is_minor'}
response = self.app.get('/api/person', query_string=query_string)
document = loads(response.data)
people = document['data']
self.assertEqual(['1', '2'], list(map(itemgetter('id'), people)))

def test_sorting_hybrid_expression(self):
"""Test for sorting on a hybrid property with a separate expression.

For more information, see GitHub issue #562.

"""
article1 = self.Article(id=1)
article2 = self.Article(id=2)
comment = self.Comment(id=1)
article1.comments = [comment]
self.session.add_all([article1, article2, comment])
self.session.commit()

query_string = {'sort': 'num_comments'}
response = self.app.get('/api/article', query_string=query_string)
document = loads(response.data)
articles = document['data']
self.assertEqual(['2', '1'], list(map(itemgetter('id'), articles)))

query_string = {'sort': '-num_comments'}
response = self.app.get('/api/article', query_string=query_string)
document = loads(response.data)
articles = document['data']
self.assertEqual(['1', '2'], list(map(itemgetter('id'), articles)))


class TestFetchResource(ManagerTestBase):

Expand Down
37 changes: 37 additions & 0 deletions tests/test_filtering.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
from sqlalchemy import Column
from sqlalchemy import Date
from sqlalchemy import DateTime
from sqlalchemy import func
from sqlalchemy import ForeignKey
from sqlalchemy import Integer
from sqlalchemy import select
from sqlalchemy import Time
from sqlalchemy import Unicode
from sqlalchemy.ext.associationproxy import association_proxy
Expand Down Expand Up @@ -88,6 +90,16 @@ class Article(self.Base):
author_id = Column(Integer, ForeignKey('person.id'))
author = relationship('Person', backref=backref('articles'))

@hybrid_property
def has_comments(self):
return len(self.comments) > 0

@has_comments.expression
def has_comments(cls):
return select([func.count(self.Comment.id)]).\
where(self.Comment.article_id == cls.id).\
label('num_comments') > 0

class Person(self.Base):
__tablename__ = 'person'
id = Column(Integer, primary_key=True)
Expand Down Expand Up @@ -780,6 +792,31 @@ def test_hybrid_property(self):
person = people[0]
self.assertEqual(person['id'], '1')

def test_hybrid_expression(self):
"""Test for filtering on a hybrid property with a separate expression.

For more information, see GitHub issue #562.

"""
article1 = self.Article(id=1)
article2 = self.Article(id=2)
comment = self.Comment(id=1)
comment.article = article1
self.session.add_all([article1, article2, comment])
self.session.commit()

filters = [{'name': 'has_comments', 'op': '==', 'val': True}]
response = self.search('/api/article', filters)
document = loads(response.data)
articles = document['data']
self.assertEqual(['1'], sorted(article['id'] for article in articles))

filters = [{'name': 'has_comments', 'op': '==', 'val': False}]
response = self.search('/api/article', filters)
document = loads(response.data)
articles = document['data']
self.assertEqual(['2'], sorted(article['id'] for article in articles))


class TestSimpleFiltering(ManagerTestBase):
"""Unit tests for "simple" filter query parameters.
Expand Down