summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorHunternif <hunternif@gmail.com>2019-05-02 03:57:31 +0700
committerHunternif <hunternif@gmail.com>2019-05-02 03:57:31 +0700
commit0b4bdc57894c885ba055aed74de8b9c94c8e2f60 (patch)
tree4d217e71aa02fef005afe86d8845e90fe93a9f83 /server
parent82facef4aa1f1ede518acf1435d6ed98d37f8df1 (diff)
server: implement median for posts, for any query
Diffstat (limited to 'server')
-rw-r--r--server/szurubooru/api/metric_api.py9
-rw-r--r--server/szurubooru/api/post_api.py19
-rw-r--r--server/szurubooru/tests/api/test_metric_retrieving.py2
-rw-r--r--server/szurubooru/tests/api/test_post_retrieving.py43
4 files changed, 71 insertions, 2 deletions
diff --git a/server/szurubooru/api/metric_api.py b/server/szurubooru/api/metric_api.py
index 2b87a5d..29aa7a2 100644
--- a/server/szurubooru/api/metric_api.py
+++ b/server/szurubooru/api/metric_api.py
@@ -82,8 +82,13 @@ def get_post_metrics_median(
query_text = ctx.get_param_as_string(
'query',
default='%s:%f..%f' % (tag_name, metric.min, metric.max))
- count = _search_executor.count(query_text)
- _, results = _search_executor.execute(query_text, ceil(count/2) - 1, 1)
+ total_count = _search_executor.count(query_text)
+ offset = ceil(total_count/2) - 1
+ _, results = _search_executor.execute(query_text, offset, 1)
return {
+ 'query': query_text,
+ 'offset': offset,
+ 'limit': 1,
+ 'total': len(results),
'results': list([_serialize_post_metric(ctx, pm) for pm in results])
}
diff --git a/server/szurubooru/api/post_api.py b/server/szurubooru/api/post_api.py
index 95c0ebc..ffbf34d 100644
--- a/server/szurubooru/api/post_api.py
+++ b/server/szurubooru/api/post_api.py
@@ -1,3 +1,4 @@
+from math import ceil
from typing import Optional, Dict, List
from datetime import datetime
from szurubooru import db, model, errors, rest, search
@@ -277,3 +278,21 @@ def get_posts_by_image(
for lookalike in lookalikes
],
}
+
+
+@rest.routes.get('/posts/median/?')
+def get_posts_median(
+ ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response:
+ auth.verify_privilege(ctx.user, 'posts:list')
+ _search_executor_config.user = ctx.user
+ query_text = ctx.get_param_as_string('query', default='')
+ total_count = _search_executor.count(query_text)
+ offset = ceil(total_count / 2) - 1
+ _, results = _search_executor.execute(query_text, offset, 1)
+ return {
+ 'query': query_text,
+ 'offset': offset,
+ 'limit': 1,
+ 'total': len(results),
+ 'results': list([_serialize_post(ctx, post) for post in results])
+ }
diff --git a/server/szurubooru/tests/api/test_metric_retrieving.py b/server/szurubooru/tests/api/test_metric_retrieving.py
index 901786d..2d6d6cd 100644
--- a/server/szurubooru/tests/api/test_metric_retrieving.py
+++ b/server/szurubooru/tests/api/test_metric_retrieving.py
@@ -45,6 +45,8 @@ def test_median(
user=user_factory(rank=model.User.RANK_REGULAR)),
{'tag_name': 'mytag'})
if not expected_value:
+ assert response['total'] == 0
assert len(response['results']) == 0
else:
+ assert response['total'] == 1
assert response['results'][0]['value'] == expected_value
diff --git a/server/szurubooru/tests/api/test_post_retrieving.py b/server/szurubooru/tests/api/test_post_retrieving.py
index 7270547..1e4ed03 100644
--- a/server/szurubooru/tests/api/test_post_retrieving.py
+++ b/server/szurubooru/tests/api/test_post_retrieving.py
@@ -8,6 +8,8 @@ from szurubooru.func import posts
@pytest.fixture(autouse=True)
def inject_config(config_injector):
config_injector({
+ 'data_url': 'http://example.com/',
+ 'secret': 'test',
'privileges': {
'posts:list': model.User.RANK_REGULAR,
'posts:view': model.User.RANK_REGULAR,
@@ -104,3 +106,44 @@ def test_trying_to_retrieve_single_without_privileges(
api.post_api.get_post(
context_factory(user=user_factory(rank=model.User.RANK_ANONYMOUS)),
{'post_id': 999})
+
+
+@pytest.mark.parametrize('query,expected_id', [
+ ('sort:id,asc', 2),
+ ('sort:id,asc id:2..', 2),
+ ('sort:id,desc id:2..', 3),
+ ('sort:id,asc id:3..', 3),
+ ('sort:id,desc id:3..', 3),
+ ('sort:id id:4..', None),
+ ('sort:tag-count', 3),
+ ('sort:tag-count,asc id:..2', 1),
+ ('sort:tag-count,desc id:..2', 2),
+])
+def test_median(
+ query,
+ expected_id,
+ post_factory,
+ tag_factory,
+ context_factory,
+ user_factory):
+ tag1 = tag_factory()
+ tag2 = tag_factory()
+ tag3 = tag_factory()
+ post1 = post_factory(id=1, tags=[tag1])
+ post2 = post_factory(id=2, tags=[tag1, tag2, tag3])
+ post3 = post_factory(id=3, tags=[tag1, tag2])
+ db.session.add_all([tag1, tag2, tag3, post1, post2, post3])
+ db.session.flush()
+ with patch('szurubooru.func.comments.serialize_comment'), \
+ patch('szurubooru.func.users.serialize_micro_user'), \
+ patch('szurubooru.func.posts.files.has'):
+ response = api.post_api.get_posts_median(
+ context_factory(
+ params={'query': query},
+ user=user_factory(rank=model.User.RANK_REGULAR)))
+ if not expected_id:
+ assert response['total'] == 0
+ assert len(response['results']) == 0
+ else:
+ assert response['total'] == 1
+ assert response['results'][0]['id'] == expected_id