server/search: fix missing default search order

This commit is contained in:
rr- 2016-04-16 18:55:04 +02:00
parent fa6b808659
commit c71c082000
4 changed files with 81 additions and 65 deletions

View file

@ -69,6 +69,9 @@ def _apply_str_criterion_to_column(column, query, criterion):
return query.filter(expr)
class BaseSearchConfig(object):
ORDER_DESC = 1
ORDER_ASC = 2
def create_query(self, session):
raise NotImplementedError()

View file

@ -9,9 +9,6 @@ class SearchExecutor(object):
delegates sqlalchemy filter decoration to SearchConfig instances.
'''
ORDER_DESC = 1
ORDER_ASC = 2
def __init__(self, search_config):
self._search_config = search_config
@ -52,13 +49,13 @@ class SearchExecutor(object):
def _handle_key_value(self, query, key, value, negated):
if key == 'order':
if value.count(',') == 0:
order = self.ORDER_ASC
order = None
elif value.count(',') == 1:
value, order_str = value.split(',')
if order_str == 'asc':
order = self.ORDER_ASC
order = self._search_config.ORDER_ASC
elif order_str == 'desc':
order = self.ORDER_DESC
order = self._search_config.ORDER_DESC
else:
raise errors.SearchError(
'Unknown search direction: %r.' % order_str)
@ -66,10 +63,12 @@ class SearchExecutor(object):
raise errors.SearchError(
'Too many commas in order search token.')
if negated:
if order == self.ORDER_DESC:
order = self.ORDER_ASC
if order == self._search_config.ORDER_DESC:
order = self._search_config.ORDER_ASC
elif order == self._search_config.ORDER_ASC:
order = self._search_config.ORDER_DESC
else:
order = self.ORDER_DESC
order = -1
return self._handle_order(query, value, order)
elif key == 'special':
return self._handle_special(query, value, negated)
@ -100,8 +99,17 @@ class SearchExecutor(object):
def _handle_order(self, query, value, order):
if value in self._search_config.order_columns:
column = self._search_config.order_columns[value]
if order == self.ORDER_ASC:
column, default_order = self._search_config.order_columns[value]
if order is None:
order = default_order
elif order == -1:
if default_order == self._search_config.ORDER_ASC:
order = self._search_config.ORDER_DESC
elif default_order == self._search_config.ORDER_DESC:
order = self._search_config.ORDER_ASC
else:
order = self._search_config.ORDER_ASC
if order == self._search_config.ORDER_ASC:
column = column.asc()
else:
column = column.desc()

View file

@ -35,11 +35,11 @@ class UserSearchConfig(BaseSearchConfig):
def order_columns(self):
return {
'random': func.random(),
'name': db.User.name,
'creation-date': db.User.creation_time,
'creation-time': db.User.creation_time,
'last-login-date': db.User.last_login_time,
'last-login-time': db.User.last_login_time,
'login-date': db.User.last_login_time,
'login-time': db.User.last_login_time,
'name': (db.User.name, self.ORDER_ASC),
'creation-date': (db.User.creation_time, self.ORDER_DESC),
'creation-time': (db.User.creation_time, self.ORDER_DESC),
'last-login-date': (db.User.last_login_time, self.ORDER_DESC),
'last-login-time': (db.User.last_login_time, self.ORDER_DESC),
'login-date': (db.User.last_login_time, self.ORDER_DESC),
'login-time': (db.User.last_login_time, self.ORDER_DESC),
}

View file

@ -1,19 +1,7 @@
from datetime import datetime
import datetime
import pytest
from szurubooru import db, errors, search
def mock_user(name):
user = db.User()
user.name = name
user.password = 'dummy'
user.password_salt = 'dummy'
user.password_hash = 'dummy'
user.email = 'dummy'
user.rank = 'dummy'
user.creation_time = datetime(1997, 1, 1)
user.avatar_style = db.User.AVATAR_GRAVATAR
return user
@pytest.fixture
def executor(session):
search_config = search.UserSearchConfig()
@ -29,7 +17,6 @@ def verify_unpaged(session, executor):
assert actual_user_names == expected_user_names
return verify
# -----------------------------------------------------------------------------
@pytest.mark.parametrize('input,expected_user_names', [
('creation-time:2014', ['u1', 'u2']),
('creation-date:2014', ['u1', 'u2']),
@ -53,17 +40,16 @@ def verify_unpaged(session, executor):
('-creation-date:2014-01,2015', ['u2']),
])
def test_filter_by_creation_time(
verify_unpaged, session, input, expected_user_names):
user1 = mock_user('u1')
user2 = mock_user('u2')
user3 = mock_user('u3')
user1.creation_time = datetime(2014, 1, 1)
user2.creation_time = datetime(2014, 6, 1)
user3.creation_time = datetime(2015, 1, 1)
verify_unpaged, session, input, expected_user_names, user_factory):
user1 = user_factory(name='u1')
user2 = user_factory(name='u2')
user3 = user_factory(name='u3')
user1.creation_time = datetime.datetime(2014, 1, 1)
user2.creation_time = datetime.datetime(2014, 6, 1)
user3.creation_time = datetime.datetime(2015, 1, 1)
session.add_all([user1, user2, user3])
verify_unpaged(input, expected_user_names)
# -----------------------------------------------------------------------------
@pytest.mark.parametrize('input,expected_user_names', [
('name:user1', ['user1']),
('name:user2', ['user2']),
@ -82,41 +68,41 @@ def test_filter_by_creation_time(
('name:user1,user2', ['user1', 'user2']),
('-name:user1,user3', ['user2']),
])
def test_filter_by_name(session, verify_unpaged, input, expected_user_names):
session.add(mock_user('user1'))
session.add(mock_user('user2'))
session.add(mock_user('user3'))
def test_filter_by_name(
session, verify_unpaged, input, expected_user_names, user_factory):
session.add(user_factory(name='user1'))
session.add(user_factory(name='user2'))
session.add(user_factory(name='user3'))
verify_unpaged(input, expected_user_names)
# -----------------------------------------------------------------------------
@pytest.mark.parametrize('input,expected_user_names', [
('', ['u1', 'u2']),
('u1', ['u1']),
('u2', ['u2']),
('u1,u2', ['u1', 'u2']),
])
def test_anonymous(session, verify_unpaged, input, expected_user_names):
session.add(mock_user('u1'))
session.add(mock_user('u2'))
def test_anonymous(
session, verify_unpaged, input, expected_user_names, user_factory):
session.add(user_factory(name='u1'))
session.add(user_factory(name='u2'))
verify_unpaged(input, expected_user_names)
# -----------------------------------------------------------------------------
@pytest.mark.parametrize('input,expected_user_names', [
('creation-time:2014 u1', ['u1']),
('creation-time:2014 u2', ['u2']),
('creation-time:2016 u2', []),
])
def test_combining_tokens(session, verify_unpaged, input, expected_user_names):
user1 = mock_user('u1')
user2 = mock_user('u2')
user3 = mock_user('u3')
user1.creation_time = datetime(2014, 1, 1)
user2.creation_time = datetime(2014, 6, 1)
user3.creation_time = datetime(2015, 1, 1)
def test_combining_tokens(
session, verify_unpaged, input, expected_user_names, user_factory):
user1 = user_factory(name='u1')
user2 = user_factory(name='u2')
user3 = user_factory(name='u3')
user1.creation_time = datetime.datetime(2014, 1, 1)
user2.creation_time = datetime.datetime(2014, 6, 1)
user3.creation_time = datetime.datetime(2015, 1, 1)
session.add_all([user1, user2, user3])
verify_unpaged(input, expected_user_names)
# -----------------------------------------------------------------------------
@pytest.mark.parametrize(
'page,page_size,expected_total_count,expected_user_names', [
(1, 1, 2, ['u1']),
@ -126,17 +112,16 @@ def test_combining_tokens(session, verify_unpaged, input, expected_user_names):
(0, 0, 2, []),
])
def test_paging(
session, executor, page, page_size,
session, executor, user_factory, page, page_size,
expected_total_count, expected_user_names):
session.add(mock_user('u1'))
session.add(mock_user('u2'))
session.add(user_factory(name='u1'))
session.add(user_factory(name='u2'))
actual_count, actual_users = executor.execute(
session, '', page=page, page_size=page_size)
actual_user_names = [u.name for u in actual_users]
assert actual_count == expected_total_count
assert actual_user_names == expected_user_names
# -----------------------------------------------------------------------------
@pytest.mark.parametrize('input,expected_user_names', [
('', ['u1', 'u2']),
('order:name', ['u1', 'u2']),
@ -146,12 +131,32 @@ def test_paging(
('-order:name,asc', ['u2', 'u1']),
('-order:name,desc', ['u1', 'u2']),
])
def test_order_by_name(session, verify_unpaged, input, expected_user_names):
session.add(mock_user('u2'))
session.add(mock_user('u1'))
def test_order_by_name(
session, verify_unpaged, input, expected_user_names, user_factory):
session.add(user_factory(name='u2'))
session.add(user_factory(name='u1'))
verify_unpaged(input, expected_user_names)
@pytest.mark.parametrize('input,expected_user_names', [
('', ['u1', 'u2', 'u3']),
('order:creation-date', ['u3', 'u2', 'u1']),
('-order:creation-date', ['u1', 'u2', 'u3']),
('order:creation-date,asc', ['u1', 'u2', 'u3']),
('order:creation-date,desc', ['u3', 'u2', 'u1']),
('-order:creation-date,asc', ['u3', 'u2', 'u1']),
('-order:creation-date,desc', ['u1', 'u2', 'u3']),
])
def test_order_by_name(
session, verify_unpaged, input, expected_user_names, user_factory):
user1 = user_factory(name='u1')
user2 = user_factory(name='u2')
user3 = user_factory(name='u3')
user1.creation_time = datetime.datetime(1991, 1, 1)
user2.creation_time = datetime.datetime(1991, 1, 2)
user3.creation_time = datetime.datetime(1991, 1, 3)
session.add_all([user3, user1, user2])
verify_unpaged(input, expected_user_names)
# -----------------------------------------------------------------------------
@pytest.mark.parametrize('input,expected_error', [
('creation-date:..', errors.SearchError),
('creation-date:bad..', errors.ValidationError),