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

services: Add locale to search params via args #594

Closed
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
8 changes: 8 additions & 0 deletions invenio_records_resources/resources/records/args.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-

Check failure on line 1 in invenio_records_resources/resources/records/args.py

View workflow job for this annotation

GitHub Actions / Tests / Tests (3.9, postgresql14, opensearch2)

isort-check """Schemas for parameter parsing.""" +from flask_resources.parsers import MultiDictSchema from invenio_i18n import get_locale - -from flask_resources.parsers import MultiDictSchema from marshmallow import fields, post_load, validate

Check failure on line 1 in invenio_records_resources/resources/records/args.py

View workflow job for this annotation

GitHub Actions / Tests / Tests (3.12, postgresql14, opensearch2)

isort-check """Schemas for parameter parsing.""" +from flask_resources.parsers import MultiDictSchema from invenio_i18n import get_locale - -from flask_resources.parsers import MultiDictSchema from marshmallow import fields, post_load, validate
#
# Copyright (C) 2020 CERN.
# Copyright (C) 2020 Northwestern University.
Expand All @@ -9,6 +9,8 @@

"""Schemas for parameter parsing."""

from invenio_i18n import get_locale

from flask_resources.parsers import MultiDictSchema
from marshmallow import fields, post_load, validate

Expand All @@ -29,3 +31,9 @@
for k in set(original_data.keys()) - set(data.keys()):
data["facets"][k] = original_data.getlist(k)
return data

@post_load
def inject_locale(self, data, **kwargs):
"""Inject locale from request context into the args."""
data["locale"] = str(get_locale())
return data
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def apply(self, identity, search, params):
raise QuerystringValidationError("Invalid 'suggest' parameter.")

if query_str:
query = parser_cls(identity).parse(query_str)
query = parser_cls(identity).parse(query_str, locale=params.get("locale"))
search = search.query(query)

return search
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ def __init__(self, identity=None, extra_params=None, tree_transformer_cls=None):
# fields is not removed from extra params since if given it must be
# used in both querystring and multi match
self._fields = self.extra_params.get("fields") or []
self._dynamic_fields = self.extra_params.pop("dynamic_fields", None) or []

@property
def allow_list(self):
Expand Down Expand Up @@ -117,8 +118,12 @@ def factory(cls, tree_transformer_cls=None, **extra_params):
tree_transformer_cls=tree_transformer_cls,
)

def parse(self, query_str):
def parse(self, query_str, locale=None):
"""Parse the query."""
if locale and self.extra_params.get("fields", None):
self.extra_params["fields"] += [
field.format(locale=locale) for field in self._dynamic_fields
]
try:
# We parse the Lucene query syntax in Python, so we know upfront
# if the syntax is correct before executing it in the search engine
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ def __init__(self, identity=None, extra_params=None, **kwargs):
super().__init__(identity=identity, extra_params=extra_params)
self.extra_params.setdefault("type", "bool_prefix")

def parse(self, query_str):
def parse(self, query_str, locale=None):
"""Parse the query."""
if locale and self.extra_params.get("fields", None):
self.extra_params["fields"] += [
field.format(locale=locale) for field in self._dynamic_fields
]
return dsl.Q("multi_match", query=query_str, **self.extra_params)
6 changes: 3 additions & 3 deletions tests/resources/test_resource_faceting.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ def test_links_keep_facets(client, headers, three_indexed_records):
response_links = response.json["links"]
expected_links = {
"self": (
"https://127.0.0.1:5000/api/mocks?"
"https://127.0.0.1:5000/api/mocks?locale=en&"
"page=1&size=25&sort=newest&type=A%2A%2AB"
),
}
Expand All @@ -293,11 +293,11 @@ def test_links_keep_repeated_facets(client, headers, three_indexed_records):
response_links = response.json["links"]
expected_links = {
"self": (
"https://127.0.0.1:5000/api/mocks?page=1&size=1&sort=newest"
"https://127.0.0.1:5000/api/mocks?locale=en&page=1&size=1&sort=newest"
"&type=B&type=A"
),
"next": (
"https://127.0.0.1:5000/api/mocks?page=2&size=1&sort=newest"
"https://127.0.0.1:5000/api/mocks?locale=en&page=2&size=1&sort=newest"
"&type=B&type=A"
),
}
Expand Down
26 changes: 13 additions & 13 deletions tests/resources/test_resource_pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,9 @@ def test_middle_search_result_has_next_and_prev_links(

response_links = response.json["links"]
expected_links = {
"self": "https://127.0.0.1:5000/api/mocks?page=2&size=1&sort=newest",
"prev": "https://127.0.0.1:5000/api/mocks?page=1&size=1&sort=newest",
"next": "https://127.0.0.1:5000/api/mocks?page=3&size=1&sort=newest",
"self": "https://127.0.0.1:5000/api/mocks?locale=en&page=2&size=1&sort=newest",
"prev": "https://127.0.0.1:5000/api/mocks?locale=en&page=1&size=1&sort=newest",
"next": "https://127.0.0.1:5000/api/mocks?locale=en&page=3&size=1&sort=newest",
}

# NOTE: This is done so that we only test for pagination links
Expand All @@ -129,8 +129,8 @@ def test_first_search_result_has_next_and_no_prev_link(

response_links = response.json["links"]
expected_links = {
"self": "https://127.0.0.1:5000/api/mocks?page=1&size=1&sort=newest",
"next": "https://127.0.0.1:5000/api/mocks?page=2&size=1&sort=newest",
"self": "https://127.0.0.1:5000/api/mocks?locale=en&page=1&size=1&sort=newest",
"next": "https://127.0.0.1:5000/api/mocks?locale=en&page=2&size=1&sort=newest",
}
for key, url in expected_links.items():
assert url == response_links[key]
Expand All @@ -145,8 +145,8 @@ def test_last_search_result_has_prev_link_and_no_next_link(

response_links = response.json["links"]
expected_links = {
"self": "https://127.0.0.1:5000/api/mocks?page=3&size=1&sort=newest",
"prev": "https://127.0.0.1:5000/api/mocks?page=2&size=1&sort=newest",
"self": "https://127.0.0.1:5000/api/mocks?locale=en&page=3&size=1&sort=newest",
"prev": "https://127.0.0.1:5000/api/mocks?locale=en&page=2&size=1&sort=newest",
}
for key, url in expected_links.items():
assert url == response_links[key]
Expand All @@ -161,8 +161,8 @@ def test_beyond_last_search_has_prev_link_and_no_next_link(

response_links = response.json["links"]
expected_links = {
"self": "https://127.0.0.1:5000/api/mocks?page=4&size=1&sort=newest",
"prev": "https://127.0.0.1:5000/api/mocks?page=3&size=1&sort=newest",
"self": "https://127.0.0.1:5000/api/mocks?locale=en&page=4&size=1&sort=newest",
"prev": "https://127.0.0.1:5000/api/mocks?locale=en&page=3&size=1&sort=newest",
}
for key, url in expected_links.items():
assert url == response_links[key]
Expand All @@ -177,7 +177,7 @@ def test_beyond_beyond_last_search_has_no_prev_or_next_link(

response_links = response.json["links"]
expected_links = {
"self": "https://127.0.0.1:5000/api/mocks?page=5&size=1&sort=newest",
"self": "https://127.0.0.1:5000/api/mocks?locale=en&page=5&size=1&sort=newest",
}
for key, url in expected_links.items():
assert url == response_links[key]
Expand All @@ -192,15 +192,15 @@ def test_searchstring_is_preserved(client, headers, three_indexed_records):
response_links = response.json["links"]
expected_links = {
"self": (
"https://127.0.0.1:5000/api/mocks?page=2&q=test%20foo&size=1"
"https://127.0.0.1:5000/api/mocks?locale=en&page=2&q=test%20foo&size=1"
"&sort=bestmatch"
),
"prev": (
"https://127.0.0.1:5000/api/mocks?page=1&q=test%20foo&size=1"
"https://127.0.0.1:5000/api/mocks?locale=en&page=1&q=test%20foo&size=1"
"&sort=bestmatch"
),
"next": (
"https://127.0.0.1:5000/api/mocks?page=3&q=test%20foo&size=1"
"https://127.0.0.1:5000/api/mocks?locale=en&page=3&q=test%20foo&size=1"
"&sort=bestmatch"
),
}
Expand Down
18 changes: 13 additions & 5 deletions tests/resources/test_resource_sorting.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,12 @@ def test_sort_in_links_no_matter_if_sort_in_url(client, headers, three_indexed_r

response_links = response.json["links"]
expected_links = {
"self": ("https://127.0.0.1:5000/api/mocks?page=1&size=1&sort=newest"),
"next": ("https://127.0.0.1:5000/api/mocks?page=2&size=1&sort=newest"),
"self": (
"https://127.0.0.1:5000/api/mocks?locale=en&page=1&size=1&sort=newest"
),
"next": (
"https://127.0.0.1:5000/api/mocks?locale=en&page=2&size=1&sort=newest"
),
}
# NOTE: This is done so that we only test for pagination links
for key, url in expected_links.items():
Expand All @@ -113,8 +117,12 @@ def test_sort_in_links_no_matter_if_sort_in_url(client, headers, three_indexed_r

response_links = response.json["links"]
expected_links = {
"self": ("https://127.0.0.1:5000/api/mocks?page=1&size=1&sort=newest"),
"next": ("https://127.0.0.1:5000/api/mocks?page=2&size=1&sort=newest"),
"self": (
"https://127.0.0.1:5000/api/mocks?locale=en&page=1&size=1&sort=newest"
),
"next": (
"https://127.0.0.1:5000/api/mocks?locale=en&page=2&size=1&sort=newest"
),
}
for key, url in expected_links.items():
assert url == response_links[key]
Expand All @@ -126,7 +134,7 @@ def test_searchstring_is_preserved(client, headers, three_indexed_records):
response_links = response.json["links"]
expected_links = {
"self": (
"https://127.0.0.1:5000/api/mocks?page=1&q=the%20quick&size=25"
"https://127.0.0.1:5000/api/mocks?locale=en&page=1&q=the%20quick&size=25"
"&sort=newest"
),
}
Expand Down
Loading