diff options
| author | Hunternif <hunternif@gmail.com> | 2019-05-02 03:57:31 +0700 |
|---|---|---|
| committer | Hunternif <hunternif@gmail.com> | 2019-05-02 03:57:31 +0700 |
| commit | 0b4bdc57894c885ba055aed74de8b9c94c8e2f60 (patch) | |
| tree | 4d217e71aa02fef005afe86d8845e90fe93a9f83 /server | |
| parent | 82facef4aa1f1ede518acf1435d6ed98d37f8df1 (diff) | |
server: implement median for posts, for any query
Diffstat (limited to 'server')
| -rw-r--r-- | server/szurubooru/api/metric_api.py | 9 | ||||
| -rw-r--r-- | server/szurubooru/api/post_api.py | 19 | ||||
| -rw-r--r-- | server/szurubooru/tests/api/test_metric_retrieving.py | 2 | ||||
| -rw-r--r-- | server/szurubooru/tests/api/test_post_retrieving.py | 43 |
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 |