server/general: cosmetic fixes

This commit is contained in:
rr- 2016-06-05 10:39:56 +02:00
parent 508cb6e7ab
commit f3bb6c28a1
12 changed files with 202 additions and 201 deletions

View File

@ -2,8 +2,8 @@ import falcon
from szurubooru import errors
from szurubooru.func import net
def _lower_first(input):
return input[0].lower() + input[1:]
def _lower_first(source):
return source[0].lower() + source[1:]
def _param_wrapper(func):
def wrapper(self, name, required=False, default=None, **kwargs):
@ -11,10 +11,10 @@ def _param_wrapper(func):
value = self.input[name]
try:
value = func(self, value, **kwargs)
except errors.InvalidParameterError as e:
except errors.InvalidParameterError as ex:
raise errors.InvalidParameterError(
'Parameter %r is invalid: %s' % (
name, _lower_first(str(e))))
name, _lower_first(str(ex))))
return value
if not required:
return default

View File

@ -1,10 +1,4 @@
import sqlalchemy
from szurubooru import db, errors
from szurubooru.func import util
from szurubooru.search import criteria, tokens
def wildcard_transformer(value):
return value.replace('*', '%')
from szurubooru.search import tokens
class BaseSearchConfig(object):
SORT_ASC = tokens.SortToken.SORT_ASC
@ -34,127 +28,3 @@ class BaseSearchConfig(object):
@property
def sort_columns(self):
return {}
@staticmethod
def _apply_num_criterion_to_column(column, criterion):
'''
Decorate SQLAlchemy filter on given column using supplied criterion.
'''
try:
if isinstance(criterion, criteria.PlainCriterion):
expr = column == int(criterion.value)
elif isinstance(criterion, criteria.ArrayCriterion):
expr = column.in_(int(value) for value in criterion.values)
elif isinstance(criterion, criteria.RangedCriterion):
assert criterion.min_value != '' \
or criterion.max_value != ''
if criterion.min_value != '' and criterion.max_value != '':
expr = column.between(
int(criterion.min_value), int(criterion.max_value))
elif criterion.min_value != '':
expr = column >= int(criterion.min_value)
elif criterion.max_value != '':
expr = column <= int(criterion.max_value)
else:
assert False
except ValueError:
raise errors.SearchError(
'Criterion value %r must be a number.' % (criterion,))
return expr
@staticmethod
def _create_num_filter(column):
def wrapper(query, criterion, negated):
expr = BaseSearchConfig._apply_num_criterion_to_column(
column, criterion)
if negated:
expr = ~expr
return query.filter(expr)
return wrapper
@staticmethod
def _apply_str_criterion_to_column(
column, criterion, transformer=wildcard_transformer):
'''
Decorate SQLAlchemy filter on given column using supplied criterion.
'''
if isinstance(criterion, criteria.PlainCriterion):
expr = column.ilike(transformer(criterion.value))
elif isinstance(criterion, criteria.ArrayCriterion):
expr = sqlalchemy.sql.false()
for value in criterion.values:
expr = expr | column.ilike(transformer(value))
elif isinstance(criterion, criteria.RangedCriterion):
raise errors.SearchError(
'Composite token %r is invalid in this context.' % (criterion,))
else:
assert False
return expr
@staticmethod
def _create_str_filter(column, transformer=wildcard_transformer):
def wrapper(query, criterion, negated):
expr = BaseSearchConfig._apply_str_criterion_to_column(
column, criterion, transformer)
if negated:
expr = ~expr
return query.filter(expr)
return wrapper
@staticmethod
def _apply_date_criterion_to_column(column, criterion):
'''
Decorate SQLAlchemy filter on given column using supplied criterion.
Parse the datetime inside the criterion.
'''
if isinstance(criterion, criteria.PlainCriterion):
min_date, max_date = util.parse_time_range(criterion.value)
expr = column.between(min_date, max_date)
elif isinstance(criterion, criteria.ArrayCriterion):
expr = sqlalchemy.sql.false()
for value in criterion.values:
min_date, max_date = util.parse_time_range(value)
expr = expr | column.between(min_date, max_date)
elif isinstance(criterion, criteria.RangedCriterion):
assert criterion.min_value or criterion.max_value
if criterion.min_value and criterion.max_value:
min_date = util.parse_time_range(criterion.min_value)[0]
max_date = util.parse_time_range(criterion.max_value)[1]
expr = column.between(min_date, max_date)
elif criterion.min_value:
min_date = util.parse_time_range(criterion.min_value)[0]
expr = column >= min_date
elif criterion.max_value:
max_date = util.parse_time_range(criterion.max_value)[1]
expr = column <= max_date
else:
assert False
return expr
@staticmethod
def _create_date_filter(column):
def wrapper(query, criterion, negated):
expr = BaseSearchConfig._apply_date_criterion_to_column(
column, criterion)
if negated:
expr = ~expr
return query.filter(expr)
return wrapper
@staticmethod
def _create_subquery_filter(
left_id_column,
right_id_column,
filter_column,
filter_factory,
subquery_decorator=None):
filter_func = filter_factory(filter_column)
def wrapper(query, criterion, negated):
subquery = db.session.query(right_id_column.label('foreign_id'))
if subquery_decorator:
subquery = subquery_decorator(subquery)
subquery = subquery.options(sqlalchemy.orm.lazyload('*'))
subquery = filter_func(subquery, criterion, negated)
subquery = subquery.subquery('t')
return query.filter(left_id_column.in_(subquery))
return wrapper

View File

@ -1,5 +1,6 @@
from sqlalchemy.sql.expression import func
from szurubooru import db
from szurubooru.search.configs import util as search_util
from szurubooru.search.configs.base_search_config import BaseSearchConfig
class CommentSearchConfig(BaseSearchConfig):
@ -11,22 +12,22 @@ class CommentSearchConfig(BaseSearchConfig):
@property
def anonymous_filter(self):
return self._create_str_filter(db.Comment.text)
return search_util.create_str_filter(db.Comment.text)
@property
def named_filters(self):
return {
'id': self._create_num_filter(db.Comment.comment_id),
'post': self._create_num_filter(db.Comment.post_id),
'user': self._create_str_filter(db.User.name),
'author': self._create_str_filter(db.User.name),
'text': self._create_str_filter(db.Comment.text),
'creation-date': self._create_date_filter(db.Comment.creation_time),
'creation-time': self._create_date_filter(db.Comment.creation_time),
'last-edit-date': self._create_date_filter(db.Comment.last_edit_time),
'last-edit-time': self._create_date_filter(db.Comment.last_edit_time),
'edit-date': self._create_date_filter(db.Comment.last_edit_time),
'edit-time': self._create_date_filter(db.Comment.last_edit_time),
'id': search_util.create_num_filter(db.Comment.comment_id),
'post': search_util.create_num_filter(db.Comment.post_id),
'user': search_util.create_str_filter(db.User.name),
'author': search_util.create_str_filter(db.User.name),
'text': search_util.create_str_filter(db.Comment.text),
'creation-date': search_util.create_date_filter(db.Comment.creation_time),
'creation-time': search_util.create_date_filter(db.Comment.creation_time),
'last-edit-date': search_util.create_date_filter(db.Comment.last_edit_time),
'last-edit-time': search_util.create_date_filter(db.Comment.last_edit_time),
'edit-date': search_util.create_date_filter(db.Comment.last_edit_time),
'edit-time': search_util.create_date_filter(db.Comment.last_edit_time),
}
@property

View File

@ -3,6 +3,7 @@ from sqlalchemy.sql.expression import func
from szurubooru import db, errors
from szurubooru.func import util
from szurubooru.search import criteria, tokens
from szurubooru.search.configs import util as search_util
from szurubooru.search.configs.base_search_config import BaseSearchConfig
def _enum_transformer(available_values, value):
@ -45,7 +46,7 @@ def _create_score_filter(score):
user_alias = aliased(db.User)
score_alias = aliased(db.PostScore)
expr = score_alias.score == score
expr = expr & BaseSearchConfig._apply_str_criterion_to_column(
expr = expr & search_util.apply_str_criterion_to_column(
user_alias.name, criterion)
if negated:
expr = ~expr
@ -106,69 +107,69 @@ class PostSearchConfig(BaseSearchConfig):
@property
def anonymous_filter(self):
return self._create_subquery_filter(
return search_util.create_subquery_filter(
db.Post.post_id,
db.PostTag.post_id,
db.TagName.name,
self._create_str_filter,
search_util.create_str_filter,
lambda subquery: subquery.join(db.Tag).join(db.TagName))
@property
def named_filters(self):
return util.unalias_dict({
'id': self._create_num_filter(db.Post.post_id),
'tag': self._create_subquery_filter(
'id': search_util.create_num_filter(db.Post.post_id),
'tag': search_util.create_subquery_filter(
db.Post.post_id,
db.PostTag.post_id,
db.TagName.name,
self._create_str_filter,
search_util.create_str_filter,
lambda subquery: subquery.join(db.Tag).join(db.TagName)),
'score': self._create_num_filter(db.Post.score),
'score': search_util.create_num_filter(db.Post.score),
('uploader', 'upload', 'submit'):
self._create_subquery_filter(
search_util.create_subquery_filter(
db.Post.user_id,
db.User.user_id,
db.User.name,
self._create_str_filter),
'comment': self._create_subquery_filter(
search_util.create_str_filter),
'comment': search_util.create_subquery_filter(
db.Post.post_id,
db.Comment.post_id,
db.User.name,
self._create_str_filter,
search_util.create_str_filter,
lambda subquery: subquery.join(db.User)),
'fav': self._create_subquery_filter(
'fav': search_util.create_subquery_filter(
db.Post.post_id,
db.PostFavorite.post_id,
db.User.name,
self._create_str_filter,
search_util.create_str_filter,
lambda subquery: subquery.join(db.User)),
'liked': _create_score_filter(1),
'disliked': _create_score_filter(-1),
'tag-count': self._create_num_filter(db.Post.tag_count),
'comment-count': self._create_num_filter(db.Post.comment_count),
'fav-count': self._create_num_filter(db.Post.favorite_count),
'note-count': self._create_num_filter(db.Post.note_count),
'feature-count': self._create_num_filter(db.Post.feature_count),
'type': self._create_str_filter(db.Post.type, _type_transformer),
'file-size': self._create_num_filter(db.Post.file_size),
'tag-count': search_util.create_num_filter(db.Post.tag_count),
'comment-count': search_util.create_num_filter(db.Post.comment_count),
'fav-count': search_util.create_num_filter(db.Post.favorite_count),
'note-count': search_util.create_num_filter(db.Post.note_count),
'feature-count': search_util.create_num_filter(db.Post.feature_count),
'type': search_util.create_str_filter(db.Post.type, _type_transformer),
'file-size': search_util.create_num_filter(db.Post.file_size),
('image-width', 'width'):
self._create_num_filter(db.Post.canvas_width),
search_util.create_num_filter(db.Post.canvas_width),
('image-height', 'height'):
self._create_num_filter(db.Post.canvas_height),
search_util.create_num_filter(db.Post.canvas_height),
('image-area', 'area'):
self._create_num_filter(db.Post.canvas_area),
search_util.create_num_filter(db.Post.canvas_area),
('creation-date', 'creation-time', 'date', 'time'):
self._create_date_filter(db.Post.creation_time),
search_util.create_date_filter(db.Post.creation_time),
('last-edit-date', 'last-edit-time', 'edit-date', 'edit-time'):
self._create_date_filter(db.Post.last_edit_time),
search_util.create_date_filter(db.Post.last_edit_time),
('comment-date', 'comment-time'):
self._create_date_filter(db.Post.last_comment_edit_time),
search_util.create_date_filter(db.Post.last_comment_edit_time),
('fav-date', 'fav-time'):
self._create_date_filter(db.Post.last_favorite_time),
search_util.create_date_filter(db.Post.last_favorite_time),
('feature-date', 'feature-time'):
self._create_date_filter(db.Post.last_feature_time),
search_util.create_date_filter(db.Post.last_feature_time),
('safety', 'rating'):
self._create_str_filter(db.Post.safety, _safety_transformer),
search_util.create_str_filter(db.Post.safety, _safety_transformer),
})
@property

View File

@ -1,4 +1,5 @@
from szurubooru import db
from szurubooru.search.configs import util as search_util
from szurubooru.search.configs.base_search_config import BaseSearchConfig
class SnapshotSearchConfig(BaseSearchConfig):
@ -11,10 +12,10 @@ class SnapshotSearchConfig(BaseSearchConfig):
@property
def named_filters(self):
return {
'type': self._create_str_filter(db.Snapshot.resource_type),
'id': self._create_str_filter(db.Snapshot.resource_repr),
'date': self._create_date_filter(db.Snapshot.creation_time),
'time': self._create_date_filter(db.Snapshot.creation_time),
'operation': self._create_str_filter(db.Snapshot.operation),
'user': self._create_str_filter(db.User.name),
'type': search_util.create_str_filter(db.Snapshot.resource_type),
'id': search_util.create_str_filter(db.Snapshot.resource_repr),
'date': search_util.create_date_filter(db.Snapshot.creation_time),
'time': search_util.create_date_filter(db.Snapshot.creation_time),
'operation': search_util.create_str_filter(db.Snapshot.operation),
'user': search_util.create_str_filter(db.User.name),
}

View File

@ -2,6 +2,7 @@ from sqlalchemy.orm import subqueryload
from sqlalchemy.sql.expression import func
from szurubooru import db
from szurubooru.func import util
from szurubooru.search.configs import util as search_util
from szurubooru.search.configs.base_search_config import BaseSearchConfig
class TagSearchConfig(BaseSearchConfig):
@ -23,33 +24,35 @@ class TagSearchConfig(BaseSearchConfig):
@property
def anonymous_filter(self):
return self._create_subquery_filter(
return search_util.create_subquery_filter(
db.Tag.tag_id,
db.TagName.tag_id,
db.TagName.name,
self._create_str_filter)
search_util.create_str_filter)
@property
def named_filters(self):
return util.unalias_dict({
'name': self._create_subquery_filter(
'name': search_util.create_subquery_filter(
db.Tag.tag_id,
db.TagName.tag_id,
db.TagName.name,
self._create_str_filter),
'category': self._create_subquery_filter(
search_util.create_str_filter),
'category': search_util.create_subquery_filter(
db.Tag.category_id,
db.TagCategory.tag_category_id,
db.TagCategory.name,
self._create_str_filter),
search_util.create_str_filter),
('creation-date', 'creation-time'):
self._create_date_filter(db.Tag.creation_time),
search_util.create_date_filter(db.Tag.creation_time),
('last-edit-date', 'last-edit-time', 'edit-date', 'edit-time'):
self._create_date_filter(db.Tag.last_edit_time),
search_util.create_date_filter(db.Tag.last_edit_time),
('usage-count', 'post-count', 'usages'):
self._create_num_filter(db.Tag.post_count),
'suggestion-count': self._create_num_filter(db.Tag.suggestion_count),
'implication-count': self._create_num_filter(db.Tag.implication_count),
search_util.create_num_filter(db.Tag.post_count),
'suggestion-count':
search_util.create_num_filter(db.Tag.suggestion_count),
'implication-count':
search_util.create_num_filter(db.Tag.implication_count),
})
@property

View File

@ -1,5 +1,6 @@
from sqlalchemy.sql.expression import func
from szurubooru import db
from szurubooru.search.configs import util as search_util
from szurubooru.search.configs.base_search_config import BaseSearchConfig
class UserSearchConfig(BaseSearchConfig):
@ -13,18 +14,18 @@ class UserSearchConfig(BaseSearchConfig):
@property
def anonymous_filter(self):
return self._create_str_filter(db.User.name)
return search_util.create_str_filter(db.User.name)
@property
def named_filters(self):
return {
'name': self._create_str_filter(db.User.name),
'creation-date': self._create_date_filter(db.User.creation_time),
'creation-time': self._create_date_filter(db.User.creation_time),
'last-login-date': self._create_date_filter(db.User.last_login_time),
'last-login-time': self._create_date_filter(db.User.last_login_time),
'login-date': self._create_date_filter(db.User.last_login_time),
'login-time': self._create_date_filter(db.User.last_login_time),
'name': search_util.create_str_filter(db.User.name),
'creation-date': search_util.create_date_filter(db.User.creation_time),
'creation-time': search_util.create_date_filter(db.User.creation_time),
'last-login-date': search_util.create_date_filter(db.User.last_login_time),
'last-login-time': search_util.create_date_filter(db.User.last_login_time),
'login-date': search_util.create_date_filter(db.User.last_login_time),
'login-time': search_util.create_date_filter(db.User.last_login_time),
}
@property

View File

@ -0,0 +1,124 @@
import sqlalchemy
from szurubooru import db, errors
from szurubooru.func import util
from szurubooru.search import criteria
def wildcard_transformer(value):
return value.replace('*', '%')
def apply_num_criterion_to_column(column, criterion):
'''
Decorate SQLAlchemy filter on given column using supplied criterion.
'''
try:
if isinstance(criterion, criteria.PlainCriterion):
expr = column == int(criterion.value)
elif isinstance(criterion, criteria.ArrayCriterion):
expr = column.in_(int(value) for value in criterion.values)
elif isinstance(criterion, criteria.RangedCriterion):
assert criterion.min_value != '' \
or criterion.max_value != ''
if criterion.min_value != '' and criterion.max_value != '':
expr = column.between(
int(criterion.min_value), int(criterion.max_value))
elif criterion.min_value != '':
expr = column >= int(criterion.min_value)
elif criterion.max_value != '':
expr = column <= int(criterion.max_value)
else:
assert False
except ValueError:
raise errors.SearchError(
'Criterion value %r must be a number.' % (criterion,))
return expr
def create_num_filter(column):
def wrapper(query, criterion, negated):
expr = apply_num_criterion_to_column(
column, criterion)
if negated:
expr = ~expr
return query.filter(expr)
return wrapper
def apply_str_criterion_to_column(
column, criterion, transformer=wildcard_transformer):
'''
Decorate SQLAlchemy filter on given column using supplied criterion.
'''
if isinstance(criterion, criteria.PlainCriterion):
expr = column.ilike(transformer(criterion.value))
elif isinstance(criterion, criteria.ArrayCriterion):
expr = sqlalchemy.sql.false()
for value in criterion.values:
expr = expr | column.ilike(transformer(value))
elif isinstance(criterion, criteria.RangedCriterion):
raise errors.SearchError(
'Composite token %r is invalid in this context.' % (criterion,))
else:
assert False
return expr
def create_str_filter(column, transformer=wildcard_transformer):
def wrapper(query, criterion, negated):
expr = apply_str_criterion_to_column(
column, criterion, transformer)
if negated:
expr = ~expr
return query.filter(expr)
return wrapper
def apply_date_criterion_to_column(column, criterion):
'''
Decorate SQLAlchemy filter on given column using supplied criterion.
Parse the datetime inside the criterion.
'''
if isinstance(criterion, criteria.PlainCriterion):
min_date, max_date = util.parse_time_range(criterion.value)
expr = column.between(min_date, max_date)
elif isinstance(criterion, criteria.ArrayCriterion):
expr = sqlalchemy.sql.false()
for value in criterion.values:
min_date, max_date = util.parse_time_range(value)
expr = expr | column.between(min_date, max_date)
elif isinstance(criterion, criteria.RangedCriterion):
assert criterion.min_value or criterion.max_value
if criterion.min_value and criterion.max_value:
min_date = util.parse_time_range(criterion.min_value)[0]
max_date = util.parse_time_range(criterion.max_value)[1]
expr = column.between(min_date, max_date)
elif criterion.min_value:
min_date = util.parse_time_range(criterion.min_value)[0]
expr = column >= min_date
elif criterion.max_value:
max_date = util.parse_time_range(criterion.max_value)[1]
expr = column <= max_date
else:
assert False
return expr
def create_date_filter(column):
def wrapper(query, criterion, negated):
expr = apply_date_criterion_to_column(
column, criterion)
if negated:
expr = ~expr
return query.filter(expr)
return wrapper
def create_subquery_filter(
left_id_column,
right_id_column,
filter_column,
filter_factory,
subquery_decorator=None):
filter_func = filter_factory(filter_column)
def wrapper(query, criterion, negated):
subquery = db.session.query(right_id_column.label('foreign_id'))
if subquery_decorator:
subquery = subquery_decorator(subquery)
subquery = subquery.options(sqlalchemy.orm.lazyload('*'))
subquery = filter_func(subquery, criterion, negated)
subquery = subquery.subquery('t')
return query.filter(left_id_column.in_(subquery))
return wrapper