oarepo-runtime 1.5.37__py3-none-any.whl → 1.5.39__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- oarepo_runtime/cli/fixtures.py +14 -7
- oarepo_runtime/cli/index.py +12 -6
- oarepo_runtime/datastreams/fixtures.py +11 -5
- oarepo_runtime/info/views.py +6 -6
- oarepo_runtime/records/__init__.py +1 -1
- oarepo_runtime/records/entity_resolvers/__init__.py +11 -4
- oarepo_runtime/records/entity_resolvers/proxies.py +0 -2
- oarepo_runtime/records/systemfields/owner.py +10 -4
- oarepo_runtime/records/systemfields/synthetic.py +2 -2
- oarepo_runtime/services/components.py +10 -0
- oarepo_runtime/services/files/components.py +17 -10
- oarepo_runtime/services/results.py +6 -6
- oarepo_runtime/services/schema/__init__.py +9 -7
- oarepo_runtime/services/schema/i18n.py +15 -4
- oarepo_runtime/services/schema/i18n_ui.py +16 -7
- oarepo_runtime/services/schema/oneofschema.py +1 -1
- oarepo_runtime/services/schema/polymorphic.py +3 -1
- oarepo_runtime/services/search.py +24 -3
- {oarepo_runtime-1.5.37.dist-info → oarepo_runtime-1.5.39.dist-info}/METADATA +1 -1
- {oarepo_runtime-1.5.37.dist-info → oarepo_runtime-1.5.39.dist-info}/RECORD +24 -24
- {oarepo_runtime-1.5.37.dist-info → oarepo_runtime-1.5.39.dist-info}/LICENSE +0 -0
- {oarepo_runtime-1.5.37.dist-info → oarepo_runtime-1.5.39.dist-info}/WHEEL +0 -0
- {oarepo_runtime-1.5.37.dist-info → oarepo_runtime-1.5.39.dist-info}/entry_points.txt +0 -0
- {oarepo_runtime-1.5.37.dist-info → oarepo_runtime-1.5.39.dist-info}/top_level.txt +0 -0
oarepo_runtime/cli/fixtures.py
CHANGED
@@ -3,8 +3,14 @@ import tqdm
|
|
3
3
|
from flask import current_app
|
4
4
|
from flask.cli import with_appcontext
|
5
5
|
from flask_login import login_user
|
6
|
-
from flask_principal import
|
7
|
-
|
6
|
+
from flask_principal import (
|
7
|
+
Identity,
|
8
|
+
RoleNeed,
|
9
|
+
UserNeed,
|
10
|
+
identity_changed,
|
11
|
+
identity_loaded,
|
12
|
+
)
|
13
|
+
from invenio_access.permissions import any_user, authenticated_user, system_identity
|
8
14
|
from invenio_accounts.models import User
|
9
15
|
|
10
16
|
from oarepo_runtime.cli import oarepo
|
@@ -39,7 +45,9 @@ def fixtures():
|
|
39
45
|
"will be committed in a single transaction and indexed together",
|
40
46
|
)
|
41
47
|
@click.option("--batch-size", help="Alias for --bulk-size", type=int)
|
42
|
-
@click.option(
|
48
|
+
@click.option(
|
49
|
+
"--identity", help="Email of the identity that will be used to import the data"
|
50
|
+
)
|
43
51
|
@with_appcontext
|
44
52
|
def load(
|
45
53
|
fixture_dir=None,
|
@@ -50,7 +58,7 @@ def load(
|
|
50
58
|
bulk_size=100,
|
51
59
|
on_background=False,
|
52
60
|
batch_size=None,
|
53
|
-
|
61
|
+
identity=None,
|
54
62
|
):
|
55
63
|
"""Loads fixtures"""
|
56
64
|
if batch_size:
|
@@ -77,12 +85,11 @@ def load(
|
|
77
85
|
identity.provides.add(any_user)
|
78
86
|
identity.provides.add(authenticated_user)
|
79
87
|
identity.provides.add(UserNeed(user.id))
|
80
|
-
for role in getattr(user,
|
88
|
+
for role in getattr(user, "roles", []):
|
81
89
|
identity.provides.add(RoleNeed(role.name))
|
82
90
|
# TODO: community roles ...
|
83
91
|
|
84
92
|
with current_app.wsgi_app.mounts["/api"].app_context():
|
85
|
-
|
86
93
|
load_fixtures(
|
87
94
|
fixture_dir,
|
88
95
|
_make_list(include),
|
@@ -93,7 +100,7 @@ def load(
|
|
93
100
|
datastreams_impl=(
|
94
101
|
AsynchronousDataStream if on_background else SynchronousDataStream
|
95
102
|
),
|
96
|
-
identity=identity
|
103
|
+
identity=identity,
|
97
104
|
)
|
98
105
|
if not on_background:
|
99
106
|
_show_stats(callback, "Load fixtures")
|
oarepo_runtime/cli/index.py
CHANGED
@@ -112,14 +112,19 @@ def reindex(model, bulk_size, verbose):
|
|
112
112
|
service = current_service_registry.get(service_id)
|
113
113
|
except KeyError:
|
114
114
|
click.secho(f"Service {service_id} not in known services:", color="red")
|
115
|
-
for known_service_id, known_service in sorted(
|
116
|
-
|
115
|
+
for known_service_id, known_service in sorted(
|
116
|
+
current_service_registry._services.items()
|
117
|
+
):
|
118
|
+
click.secho(
|
119
|
+
f" {known_service_id} -> {type(known_service).__module__}.{type(known_service).__name__}",
|
120
|
+
color="red",
|
121
|
+
)
|
117
122
|
sys.exit(1)
|
118
123
|
record_class = getattr(service.config, "record_cls", None)
|
119
124
|
|
120
125
|
id_generators = []
|
121
126
|
|
122
|
-
record_generator = RECORD_GENERATORS.get(service_id,
|
127
|
+
record_generator = RECORD_GENERATORS.get(service_id, model_records_generator)
|
123
128
|
|
124
129
|
if record_class and hasattr(service, "indexer"):
|
125
130
|
try:
|
@@ -223,9 +228,11 @@ def model_records_generator(model_class):
|
|
223
228
|
except Exception as e:
|
224
229
|
click.secho(f"Could not index {model_class}: {e}", fg="red", file=sys.stderr)
|
225
230
|
|
231
|
+
|
226
232
|
def users_record_generator(model_class):
|
227
233
|
from invenio_accounts.models import User
|
228
234
|
from invenio_users_resources.records.api import UserAggregate
|
235
|
+
|
229
236
|
try:
|
230
237
|
for x in db.session.query(User.id):
|
231
238
|
rec_id = x[0]
|
@@ -233,6 +240,5 @@ def users_record_generator(model_class):
|
|
233
240
|
except Exception as e:
|
234
241
|
click.secho(f"Could not index {model_class}: {e}", fg="red", file=sys.stderr)
|
235
242
|
|
236
|
-
|
237
|
-
|
238
|
-
}
|
243
|
+
|
244
|
+
RECORD_GENERATORS = {"users": users_record_generator}
|
@@ -35,7 +35,7 @@ def load_fixtures(
|
|
35
35
|
callback: FixturesCallback = None,
|
36
36
|
batch_size=100,
|
37
37
|
datastreams_impl=SynchronousDataStream,
|
38
|
-
identity=system_identity
|
38
|
+
identity=system_identity,
|
39
39
|
):
|
40
40
|
"""
|
41
41
|
Loads fixtures. If fixture dir is set, fixtures are loaded from that directory first.
|
@@ -64,7 +64,7 @@ def load_fixtures(
|
|
64
64
|
callback,
|
65
65
|
batch_size=batch_size,
|
66
66
|
datastreams_impl=datastreams_impl,
|
67
|
-
identity=identity
|
67
|
+
identity=identity,
|
68
68
|
)
|
69
69
|
|
70
70
|
if system_fixtures:
|
@@ -94,13 +94,19 @@ def load_fixtures(
|
|
94
94
|
callback,
|
95
95
|
batch_size=batch_size,
|
96
96
|
datastreams_impl=datastreams_impl,
|
97
|
-
identity=identity
|
97
|
+
identity=identity,
|
98
98
|
)
|
99
99
|
|
100
100
|
|
101
101
|
def _load_fixtures_from_catalogue(
|
102
|
-
catalogue,
|
103
|
-
|
102
|
+
catalogue,
|
103
|
+
fixtures,
|
104
|
+
include,
|
105
|
+
exclude,
|
106
|
+
callback,
|
107
|
+
batch_size,
|
108
|
+
datastreams_impl,
|
109
|
+
identity=system_identity,
|
104
110
|
):
|
105
111
|
for catalogue_datastream in catalogue.get_datastreams():
|
106
112
|
if catalogue_datastream.stream_name in fixtures:
|
oarepo_runtime/info/views.py
CHANGED
@@ -273,7 +273,6 @@ class InfoResource(Resource):
|
|
273
273
|
return None
|
274
274
|
return service
|
275
275
|
|
276
|
-
|
277
276
|
def _get_service_class(self, model_data):
|
278
277
|
service_id = model_data["service"]["class"]
|
279
278
|
return obj_or_import_string(service_id)
|
@@ -301,7 +300,7 @@ def get_package_version(package_name):
|
|
301
300
|
def api_url_for(endpoint, _external=True, **values):
|
302
301
|
"""API url_for."""
|
303
302
|
try:
|
304
|
-
api_app = current_app.wsgi_app.mounts[
|
303
|
+
api_app = current_app.wsgi_app.mounts["/api"]
|
305
304
|
except:
|
306
305
|
api_app = current_app
|
307
306
|
|
@@ -309,14 +308,15 @@ def api_url_for(endpoint, _external=True, **values):
|
|
309
308
|
site_url = current_app.config["SITE_UI_URL"]
|
310
309
|
current_request_context = _cv_request.get()
|
311
310
|
try:
|
312
|
-
new_context = RequestContext(app=api_app,
|
313
|
-
environ=request.environ)
|
311
|
+
new_context = RequestContext(app=api_app, environ=request.environ)
|
314
312
|
_cv_request.set(new_context)
|
315
313
|
base_url = api_app.url_for(endpoint, **values, _external=_external)
|
316
314
|
if base_url.startswith(site_api_url):
|
317
315
|
return base_url
|
318
316
|
if base_url.startswith(site_url):
|
319
317
|
return base_url.replace(site_url, site_api_url)
|
320
|
-
raise ValueError(
|
318
|
+
raise ValueError(
|
319
|
+
f"URL {base_url} does not start with {site_url} or {site_api_url}"
|
320
|
+
)
|
321
321
|
finally:
|
322
|
-
_cv_request.set(current_request_context)
|
322
|
+
_cv_request.set(current_request_context)
|
@@ -25,6 +25,6 @@ def has_draft(record, ctx):
|
|
25
25
|
"""Shortcut for links to determine if record is either a draft or a published one with a draft associated."""
|
26
26
|
if getattr(record, "is_draft", False):
|
27
27
|
return True
|
28
|
-
if getattr(record,
|
28
|
+
if getattr(record, "has_draft", False):
|
29
29
|
return True
|
30
30
|
return False
|
@@ -1,6 +1,13 @@
|
|
1
|
-
from oarepo_runtime.records.entity_resolvers.proxies import DraftProxy, RecordProxy
|
2
|
-
|
3
1
|
from invenio_records_resources.references import EntityResolver, RecordResolver
|
4
|
-
from invenio_users_resources.entity_resolvers import
|
2
|
+
from invenio_users_resources.entity_resolvers import GroupResolver, UserResolver
|
3
|
+
|
4
|
+
from oarepo_runtime.records.entity_resolvers.proxies import DraftProxy, RecordProxy
|
5
5
|
|
6
|
-
__all__ = [
|
6
|
+
__all__ = [
|
7
|
+
"DraftProxy",
|
8
|
+
"UserResolver",
|
9
|
+
"GroupResolver",
|
10
|
+
"RecordResolver",
|
11
|
+
"EntityResolver",
|
12
|
+
"RecordProxy",
|
13
|
+
]
|
@@ -17,7 +17,6 @@ from oarepo_runtime.records.systemfields import MappingSystemFieldMixin
|
|
17
17
|
|
18
18
|
|
19
19
|
class OwnerRelationManager:
|
20
|
-
|
21
20
|
def __init__(self, record_id, serialized_owners):
|
22
21
|
self._serialized_owners = serialized_owners
|
23
22
|
self._deserialized_owners = None
|
@@ -33,9 +32,13 @@ class OwnerRelationManager:
|
|
33
32
|
if self._serialized_owners is None:
|
34
33
|
deserialized_owners = []
|
35
34
|
for deserialized_owner in self._deserialized_owners or []:
|
36
|
-
serialized_owner = OwnerEntityResolverRegistry.reference_entity(
|
35
|
+
serialized_owner = OwnerEntityResolverRegistry.reference_entity(
|
36
|
+
deserialized_owner
|
37
|
+
)
|
37
38
|
if serialized_owner is None:
|
38
|
-
raise ValueError(
|
39
|
+
raise ValueError(
|
40
|
+
f"failed serialize owner; owner - {deserialized_owner}"
|
41
|
+
)
|
39
42
|
deserialized_owners.append(serialized_owner)
|
40
43
|
self._serialized_owners = deserialized_owners
|
41
44
|
return self._serialized_owners
|
@@ -44,7 +47,9 @@ class OwnerRelationManager:
|
|
44
47
|
if self._deserialized_owners is None:
|
45
48
|
self._deserialized_owners = set()
|
46
49
|
for ref in self._serialized_owners or []:
|
47
|
-
self._deserialized_owners.add(
|
50
|
+
self._deserialized_owners.add(
|
51
|
+
OwnerEntityResolverRegistry.resolve_reference(ref)
|
52
|
+
)
|
48
53
|
self._serialized_owners = None
|
49
54
|
|
50
55
|
def add(self, owner):
|
@@ -63,6 +68,7 @@ class OwnerRelationManager:
|
|
63
68
|
self._resolve()
|
64
69
|
return iter(self._deserialized_owners)
|
65
70
|
|
71
|
+
|
66
72
|
class OwnersField(MappingSystemFieldMixin, SystemField):
|
67
73
|
"""Communites system field for managing relations to communities."""
|
68
74
|
|
@@ -41,3 +41,13 @@ class OwnersComponent(ServiceComponent):
|
|
41
41
|
if new_term:
|
42
42
|
return search.filter(new_term)
|
43
43
|
return search
|
44
|
+
|
45
|
+
|
46
|
+
from datetime import datetime
|
47
|
+
|
48
|
+
|
49
|
+
class DateIssuedComponent(ServiceComponent):
|
50
|
+
def publish(self, identity, data=None, record=None, errors=None, **kwargs):
|
51
|
+
"""Create a new record."""
|
52
|
+
if "dateIssued" not in record["metadata"]:
|
53
|
+
record["metadata"]["dateIssued"] = datetime.today().strftime("%Y-%m-%d")
|
@@ -1,10 +1,11 @@
|
|
1
1
|
import mimetypes
|
2
2
|
import os
|
3
|
+
|
3
4
|
from invenio_records_resources.services.files.components import FileServiceComponent
|
4
5
|
from marshmallow.exceptions import ValidationError
|
5
6
|
|
6
|
-
class AllowedFileTypesComponent(FileServiceComponent):
|
7
7
|
|
8
|
+
class AllowedFileTypesComponent(FileServiceComponent):
|
8
9
|
def guess_content_type(self, filename: str | None) -> str | None:
|
9
10
|
if filename:
|
10
11
|
return mimetypes.guess_type(filename)[0] or "application/octet-stream"
|
@@ -22,10 +23,7 @@ class AllowedFileTypesComponent(FileServiceComponent):
|
|
22
23
|
ext_guessed = mimetypes.guess_extension(mimetype)
|
23
24
|
|
24
25
|
# Check if a valid extension is guessed and it's not the default mimetype
|
25
|
-
if
|
26
|
-
ext_guessed is not None
|
27
|
-
and mimetype != "application/octet-stream"
|
28
|
-
):
|
26
|
+
if ext_guessed is not None and mimetype != "application/octet-stream":
|
29
27
|
return ext_guessed[1:]
|
30
28
|
|
31
29
|
# Support non-standard file extensions that cannot be guessed
|
@@ -48,8 +46,17 @@ class AllowedFileTypesComponent(FileServiceComponent):
|
|
48
46
|
for file in list_files:
|
49
47
|
allowed_type = self.guess_content_type(file)
|
50
48
|
allowed_ext = self.guess_extension(file, allowed_type)
|
51
|
-
if
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
49
|
+
if (
|
50
|
+
len(self.allowed_mimetypes) > 0
|
51
|
+
and allowed_type not in self.allowed_mimetypes
|
52
|
+
):
|
53
|
+
raise ValidationError(
|
54
|
+
f"Mimetype not supported, supported mimetypes: {self.allowed_mimetypes}"
|
55
|
+
)
|
56
|
+
elif (
|
57
|
+
len(self.allowed_extensions) > 0
|
58
|
+
and allowed_ext not in self.allowed_extensions
|
59
|
+
):
|
60
|
+
raise ValidationError(
|
61
|
+
f"Extension not supported, supported extensions: {self.allowed_extensions}"
|
62
|
+
)
|
@@ -43,15 +43,15 @@ class RecordList(BaseRecordList):
|
|
43
43
|
return result
|
44
44
|
|
45
45
|
for key in result.keys():
|
46
|
-
if
|
47
|
-
for bucket in result[key][
|
48
|
-
val = bucket[
|
49
|
-
label = bucket.get(
|
46
|
+
if "buckets" in result[key]:
|
47
|
+
for bucket in result[key]["buckets"]:
|
48
|
+
val = bucket["key"]
|
49
|
+
label = bucket.get("label", "")
|
50
50
|
|
51
51
|
if not isinstance(val, str):
|
52
|
-
bucket[
|
52
|
+
bucket["key"] = str(val)
|
53
53
|
if not isinstance(label, str):
|
54
|
-
bucket[
|
54
|
+
bucket["label"] = str(label)
|
55
55
|
return result
|
56
56
|
except AttributeError:
|
57
57
|
return None
|
@@ -3,11 +3,11 @@ from .polymorphic import PolymorphicSchema
|
|
3
3
|
|
4
4
|
def consistent_resolution(*classes):
|
5
5
|
"""
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
A helper function to solve resolution order of classes.
|
7
|
+
If the classes are in a correct mro order, it will return
|
8
|
+
them in the same order. Otherwise it will try to reorder
|
9
|
+
them and remove those that are already contained in mro
|
10
|
+
of others.
|
11
11
|
"""
|
12
12
|
|
13
13
|
# remove classes that are already in mro of others
|
@@ -35,8 +35,10 @@ def consistent_resolution(*classes):
|
|
35
35
|
|
36
36
|
bases = ", ".join(cls.__name__ for cls in filtered_classes)
|
37
37
|
orig_bases = ", ".join(cls.__name__ for cls in classes)
|
38
|
-
raise TypeError(
|
39
|
-
|
38
|
+
raise TypeError(
|
39
|
+
f"Cannot create a consistent method resolution order (MRO) "
|
40
|
+
f"for bases {orig_bases}, tried {bases}"
|
41
|
+
)
|
40
42
|
|
41
43
|
|
42
44
|
__all__ = ("PolymorphicSchema", "consistent_resolution")
|
@@ -1,5 +1,6 @@
|
|
1
|
-
from functools import lru_cache
|
2
1
|
import importlib
|
2
|
+
from functools import lru_cache
|
3
|
+
|
3
4
|
import langcodes
|
4
5
|
from invenio_base.utils import obj_or_import_string
|
5
6
|
from marshmallow import Schema, ValidationError, fields, validates
|
@@ -11,7 +12,9 @@ it for each project.
|
|
11
12
|
|
12
13
|
|
13
14
|
@lru_cache
|
14
|
-
def get_i18n_schema(
|
15
|
+
def get_i18n_schema(
|
16
|
+
lang_name, value_name, value_field="marshmallow_utils.fields.SanitizedHTML"
|
17
|
+
):
|
15
18
|
@validates(lang_name)
|
16
19
|
def validate_lang(self, value):
|
17
20
|
if value != "_" and not langcodes.Language.get(value).is_valid():
|
@@ -31,7 +34,11 @@ def get_i18n_schema(lang_name, value_name, value_field="marshmallow_utils.fields
|
|
31
34
|
|
32
35
|
|
33
36
|
def MultilingualField( # noqa NOSONAR
|
34
|
-
*args,
|
37
|
+
*args,
|
38
|
+
lang_name="lang",
|
39
|
+
value_name="value",
|
40
|
+
value_field="marshmallow_utils.fields.SanitizedHTML",
|
41
|
+
**kwargs,
|
35
42
|
):
|
36
43
|
# TODO: args are not used but oarepo-model-builder-multilingual generates them
|
37
44
|
# should be fixed there and subsequently removed here
|
@@ -42,7 +49,11 @@ def MultilingualField( # noqa NOSONAR
|
|
42
49
|
|
43
50
|
|
44
51
|
def I18nStrField( # noqa NOSONAR
|
45
|
-
*args,
|
52
|
+
*args,
|
53
|
+
lang_name="lang",
|
54
|
+
value_name="value",
|
55
|
+
value_field="marshmallow_utils.fields.SanitizedHTML",
|
56
|
+
**kwargs,
|
46
57
|
):
|
47
58
|
return fields.Nested(
|
48
59
|
get_i18n_schema(lang_name, value_name, value_field),
|
@@ -1,11 +1,14 @@
|
|
1
1
|
from functools import lru_cache
|
2
2
|
|
3
|
+
from invenio_base.utils import obj_or_import_string
|
3
4
|
from marshmallow import Schema, fields
|
4
5
|
from marshmallow_utils.fields import SanitizedHTML
|
5
|
-
|
6
|
+
|
6
7
|
|
7
8
|
@lru_cache
|
8
|
-
def get_i18n_ui_schema(
|
9
|
+
def get_i18n_ui_schema(
|
10
|
+
lang_name, value_name, value_field="marshmallow_utils.fields.SanitizedHTML"
|
11
|
+
):
|
9
12
|
value_field_class = obj_or_import_string(value_field)
|
10
13
|
return type(
|
11
14
|
f"I18nUISchema_{lang_name}_{value_name}",
|
@@ -18,7 +21,11 @@ def get_i18n_ui_schema(lang_name, value_name, value_field="marshmallow_utils.fie
|
|
18
21
|
|
19
22
|
|
20
23
|
def MultilingualUIField( # noqa NOSONAR
|
21
|
-
*args,
|
24
|
+
*args,
|
25
|
+
lang_name="lang",
|
26
|
+
value_name="value",
|
27
|
+
value_field="marshmallow_utils.fields.SanitizedHTML",
|
28
|
+
**kwargs,
|
22
29
|
):
|
23
30
|
return fields.List(
|
24
31
|
fields.Nested(get_i18n_ui_schema(lang_name, value_name, value_field)),
|
@@ -27,7 +34,11 @@ def MultilingualUIField( # noqa NOSONAR
|
|
27
34
|
|
28
35
|
|
29
36
|
def I18nStrUIField( # noqa NOSONAR
|
30
|
-
*args,
|
37
|
+
*args,
|
38
|
+
lang_name="lang",
|
39
|
+
value_name="value",
|
40
|
+
value_field="marshmallow_utils.fields.SanitizedHTML",
|
41
|
+
**kwargs,
|
31
42
|
):
|
32
43
|
return fields.Nested(
|
33
44
|
get_i18n_ui_schema(lang_name, value_name, value_field),
|
@@ -59,9 +70,7 @@ def get_i18n_localized_ui_schema(lang_name, value_name):
|
|
59
70
|
def MultilingualLocalizedUIField( # noqa NOSONAR
|
60
71
|
*args, lang_name="lang", value_name="value", **kwargs
|
61
72
|
):
|
62
|
-
return fields.Nested(
|
63
|
-
get_i18n_localized_ui_schema(lang_name, value_name), **kwargs
|
64
|
-
)
|
73
|
+
return fields.Nested(get_i18n_localized_ui_schema(lang_name, value_name), **kwargs)
|
65
74
|
|
66
75
|
|
67
76
|
def I18nStrLocalizedUIField( # noqa NOSONAR
|
@@ -1,9 +1,11 @@
|
|
1
1
|
from functools import cached_property
|
2
2
|
|
3
3
|
import marshmallow as ma
|
4
|
-
|
4
|
+
|
5
|
+
# from marshmallow_oneofschema import OneOfSchema
|
5
6
|
from oarepo_runtime.services.schema.oneofschema import OneOfSchema
|
6
7
|
|
8
|
+
|
7
9
|
class PolymorphicSchema(OneOfSchema):
|
8
10
|
type_field_remove = False
|
9
11
|
|
@@ -12,6 +12,8 @@ from invenio_records_resources.services.records.params import (
|
|
12
12
|
SortParam,
|
13
13
|
)
|
14
14
|
from invenio_records_resources.services.records.queryparser import SuggestQueryParser
|
15
|
+
from invenio_search.engine import dsl
|
16
|
+
|
15
17
|
|
16
18
|
# TODO: integrate this to invenio_records_resources.services.records and remove SearchOptions class
|
17
19
|
from oarepo_runtime.i18n import lazy_gettext as _
|
@@ -25,6 +27,27 @@ except ImportError:
|
|
25
27
|
from invenio_i18n.babel import get_locale
|
26
28
|
|
27
29
|
|
30
|
+
class FuzzySuggestQueryParser(SuggestQueryParser):
|
31
|
+
def __init__(self, identity=None, extra_params=None, **kwargs):
|
32
|
+
"""Constructor."""
|
33
|
+
super().__init__(identity=identity, extra_params=extra_params)
|
34
|
+
self.fields = self.extra_params.get("fields", [])
|
35
|
+
self.extra_params.setdefault("type", "bool_prefix")
|
36
|
+
|
37
|
+
def parse(self, query_str):
|
38
|
+
"""Parse the query."""
|
39
|
+
# default behavior
|
40
|
+
multi_match_with_bool_prefix = dsl.Q(
|
41
|
+
"multi_match", query=query_str, **self.extra_params
|
42
|
+
)
|
43
|
+
# fuzziness does not seem to work with bool_prefix multimatch query, so we turn this into
|
44
|
+
# should multi match query with two clauses
|
45
|
+
multi_match_fuzzy = dsl.Q(
|
46
|
+
"multi_match", query=query_str, fields=self.fields, fuzziness="AUTO"
|
47
|
+
)
|
48
|
+
return dsl.Q("bool", should=[multi_match_with_bool_prefix, multi_match_fuzzy])
|
49
|
+
|
50
|
+
|
28
51
|
class SearchOptions(InvenioSearchOptions):
|
29
52
|
params_interpreters_cls = [
|
30
53
|
QueryStrParam,
|
@@ -114,9 +137,7 @@ class ICUSuggestParser:
|
|
114
137
|
f"{fld.field}._index_prefix^{fld.boost * fld.boost_prefix}"
|
115
138
|
)
|
116
139
|
|
117
|
-
return
|
118
|
-
fields=fields,
|
119
|
-
)
|
140
|
+
return FuzzySuggestQueryParser.factory(fields=fields)
|
120
141
|
|
121
142
|
|
122
143
|
@dataclasses.dataclass
|
@@ -10,8 +10,8 @@ oarepo_runtime/cli/base.py,sha256=94RBTa8TOSPxEyEUmYLGXaWen-XktP2-MIbTtZSlCZo,54
|
|
10
10
|
oarepo_runtime/cli/cf.py,sha256=W0JEJK2JqKubQw8qtZJxohmADDRUBode4JZAqYLDGvc,339
|
11
11
|
oarepo_runtime/cli/check.py,sha256=AvC5VHAnwmtCd8R-Caj8v6nCAREKjObTdNtLJ24aJO8,4935
|
12
12
|
oarepo_runtime/cli/configuration.py,sha256=cLXoGDtjuA5uv9ZfYFcH0C4wcadj0qWC3P_E4Bf5-z0,1061
|
13
|
-
oarepo_runtime/cli/fixtures.py,sha256=
|
14
|
-
oarepo_runtime/cli/index.py,sha256=
|
13
|
+
oarepo_runtime/cli/fixtures.py,sha256=kOstMsm2Ycoo9UIiy6f-L4KUmpRBlktf841TYaiDJYQ,5514
|
14
|
+
oarepo_runtime/cli/index.py,sha256=2dZvXtrph527YIgFTCQ8dIVsza-bZou9HBBzYRWAPTY,8243
|
15
15
|
oarepo_runtime/cli/validate.py,sha256=HpSvHQCGHlrdgdpKix9cIlzlBoJEiT1vACZdMnOUGEY,2827
|
16
16
|
oarepo_runtime/datastreams/__init__.py,sha256=_i52Ek9J8DMARST0ejZAZPzUKm55xrrlKlCSO7dl6y4,1008
|
17
17
|
oarepo_runtime/datastreams/asynchronous.py,sha256=1I1mEaTxyrcHD7LK6O9z2QX37AgeejflxynGmLreLQ0,7396
|
@@ -19,7 +19,7 @@ oarepo_runtime/datastreams/catalogue.py,sha256=D6leq-FPT3RP3SniEAXPm66v3q8ZdQnaU
|
|
19
19
|
oarepo_runtime/datastreams/datastreams.py,sha256=wnMk1UFv-cWXRO0jHwRNoJBO0cbZaHqrLnH7vgfnf78,4485
|
20
20
|
oarepo_runtime/datastreams/errors.py,sha256=WyZLU53EdFJTLv6K2ooM_M6ISjLS-U1dDw6B7guOLSc,1540
|
21
21
|
oarepo_runtime/datastreams/ext.py,sha256=ivugdVMCqwugK-5SeX14a-dMq6VaTt7DM2wFU357tR4,1406
|
22
|
-
oarepo_runtime/datastreams/fixtures.py,sha256=
|
22
|
+
oarepo_runtime/datastreams/fixtures.py,sha256=LTzRLoS3hkdP7a7wX3fCNWplaxh0DQQjxGto3p1_Luk,8691
|
23
23
|
oarepo_runtime/datastreams/json.py,sha256=OAiaH93eqpH5qNQSPKKc8K-hXKAn5lB0PUKwwZFqJSw,153
|
24
24
|
oarepo_runtime/datastreams/semi_asynchronous.py,sha256=TJWby2MDKXm5feRocoWB-8OhsShq5R9HoZ74O1rGBOk,2934
|
25
25
|
oarepo_runtime/datastreams/synchronous.py,sha256=t5lfnMkLqy3jK5zMl-nIuA0HlMPiHGjwCqZ8XQP-3GM,2595
|
@@ -41,13 +41,13 @@ oarepo_runtime/datastreams/writers/validation_errors.py,sha256=wOCXdniR6so_4Expd
|
|
41
41
|
oarepo_runtime/datastreams/writers/yaml.py,sha256=XchUJHQ58E2Mfgs8elImXbL38jFtI8Hfoye6yaR0gKI,1482
|
42
42
|
oarepo_runtime/i18n/__init__.py,sha256=h0knW_HwiyIt5TBHfdGqN7_BBYfpz1Fw6zhVy0C28fM,111
|
43
43
|
oarepo_runtime/info/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
44
|
-
oarepo_runtime/info/views.py,sha256=
|
45
|
-
oarepo_runtime/records/__init__.py,sha256=
|
44
|
+
oarepo_runtime/info/views.py,sha256=VxH6Acnif1aYnJ4HYA5hPVPX_tKme_u-LJEDiCdeU3c,11122
|
45
|
+
oarepo_runtime/records/__init__.py,sha256=3vzRsAPxl4d5QOnGyls-vUg4E6PunmR4ACObtacMAIQ,1038
|
46
46
|
oarepo_runtime/records/dumpers/__init__.py,sha256=OmzNhLdMNKibmCksnj9eTX9xPBG30dziiK3j3bAAp3k,233
|
47
47
|
oarepo_runtime/records/dumpers/edtf_interval.py,sha256=YCShZAoqBQYaxVilEVotS-jXZsxxoXO67yu2urhkaMA,1198
|
48
48
|
oarepo_runtime/records/dumpers/multilingual_dumper.py,sha256=PbNFCLsiH4XV3E1v8xga_fzlcEImHy8OXn_UKh_8VBU,1090
|
49
|
-
oarepo_runtime/records/entity_resolvers/__init__.py,sha256=
|
50
|
-
oarepo_runtime/records/entity_resolvers/proxies.py,sha256=
|
49
|
+
oarepo_runtime/records/entity_resolvers/__init__.py,sha256=UiiIT54pUu9j7qPAPfqVp4UTnXnppp0c_LtKbFnyt6Y,383
|
50
|
+
oarepo_runtime/records/entity_resolvers/proxies.py,sha256=R92Cil_sTgX-sHJtdNv82yd-F3SUfsGSNCHdwI9Zfq8,1516
|
51
51
|
oarepo_runtime/records/owners/__init__.py,sha256=R4hudCBqLRRzgCnkEjXIL7hSp068z-s6YOwYSkWyuaw,93
|
52
52
|
oarepo_runtime/records/owners/registry.py,sha256=fYgBuW5nBKn6pyz2OBgfNlynk64_yhQ9J7FzPk8QU1U,795
|
53
53
|
oarepo_runtime/records/relations/__init__.py,sha256=bDAgxl_LdKsqpGG3qluxAkQnn5u2ItJngnHQKkqzlkE,373
|
@@ -60,18 +60,18 @@ oarepo_runtime/records/systemfields/featured_file.py,sha256=MbSaYR130_o5S9gEObln
|
|
60
60
|
oarepo_runtime/records/systemfields/has_draftcheck.py,sha256=4JkMEefPLpqtPtlTgK3UT0KzTRgyw5_Qtkss2qcz5xk,1643
|
61
61
|
oarepo_runtime/records/systemfields/icu.py,sha256=tAwplzy9y7C9Dm7HqcGZsDu2AKqVGXhCbKLsFlgVWg8,5921
|
62
62
|
oarepo_runtime/records/systemfields/mapping.py,sha256=tXOK_jkdY1pOUO7_VfChfDNB8UTi21GUXaidpugTnO8,1017
|
63
|
-
oarepo_runtime/records/systemfields/owner.py,sha256=
|
63
|
+
oarepo_runtime/records/systemfields/owner.py,sha256=uv2eTss0GyMHLXaxDUFwwM_lwbbRBH_0ALxVUOKFCoI,3755
|
64
64
|
oarepo_runtime/records/systemfields/record_status.py,sha256=U3kem4-JkNsT17e0iAl3HIAZ2MvO5lY_0U757aZvTKE,935
|
65
65
|
oarepo_runtime/records/systemfields/selectors.py,sha256=VlbV3FKP2h3PLU7H4-YsI4qrb0UO_SrhJ2dcsTBGoqI,900
|
66
|
-
oarepo_runtime/records/systemfields/synthetic.py,sha256=
|
66
|
+
oarepo_runtime/records/systemfields/synthetic.py,sha256=GC7g6BZSQqVV7bFk3x6Y1E4dFgvX7VwHuIFXEDpmuSs,4238
|
67
67
|
oarepo_runtime/resources/__init__.py,sha256=v8BGrOTu_FjKzd0eozV7Q4GoGxyfybsL2cI-tbP5Pys,185
|
68
68
|
oarepo_runtime/resources/file_resource.py,sha256=Ta3bFce7l0xwqkkOMOEu9mxbB8BbKj5HUHRHmidhnl8,414
|
69
69
|
oarepo_runtime/resources/localized_ui_json_serializer.py,sha256=3V9cJaG_e1PMXKVX_wKfBp1LmbeForwHyBNYdyha4uQ,1878
|
70
70
|
oarepo_runtime/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
71
|
-
oarepo_runtime/services/components.py,sha256=
|
71
|
+
oarepo_runtime/services/components.py,sha256=FkqyFe6-5HZKJDqglQ-Smm_AIsDZ-LyWcOr1u2yGu3k,1836
|
72
72
|
oarepo_runtime/services/generators.py,sha256=V582uA813AIXnFhzqUwakmDgBOI1SQe3XZeJtUXNbwM,872
|
73
|
-
oarepo_runtime/services/results.py,sha256=
|
74
|
-
oarepo_runtime/services/search.py,sha256=
|
73
|
+
oarepo_runtime/services/results.py,sha256=gPmQ7DzX4da5zuvqQE7u-AUn_Yvz-YHt8W8DaxPbQ-M,2706
|
74
|
+
oarepo_runtime/services/search.py,sha256=eVOJ5xI9dKAVlWDM0E8mg1bYS3pGxsdpW8kTYNl5wRk,6228
|
75
75
|
oarepo_runtime/services/config/__init__.py,sha256=SCqww5sV8qh3gmev6TE8EyJbD58juIEDCm_7MEHxtSg,440
|
76
76
|
oarepo_runtime/services/config/permissions_presets.py,sha256=zApeA-2DYAlD--SzVz3vq_OFjq48Ko0pe08e4o2vxr4,6114
|
77
77
|
oarepo_runtime/services/config/service.py,sha256=2aq5jobPH22T1QqlJDommvAxJwo9aQGiqK5q-k-l9CA,4668
|
@@ -89,20 +89,20 @@ oarepo_runtime/services/facets/max_facet.py,sha256=TZ4KMKKVJHzyU1KgNne4V7IMQPu1A
|
|
89
89
|
oarepo_runtime/services/facets/nested_facet.py,sha256=y0xgjx37HsSj2xW7URxNemYTksD8hpPs7kOEfIBw22k,971
|
90
90
|
oarepo_runtime/services/facets/params.py,sha256=5z8I4wKdp-7RJK4x6cSKE92fDJI8OkUz5JR5UKWAeYg,3564
|
91
91
|
oarepo_runtime/services/files/__init__.py,sha256=K8MStrEQf_BUhvzhwPTF93Hkhwrd1dtv35LDo7iZeTM,268
|
92
|
-
oarepo_runtime/services/files/components.py,sha256=
|
92
|
+
oarepo_runtime/services/files/components.py,sha256=x6Wd-vvkqTqB1phj2a6h42DNQksN8PuR2XKaOGoNHfw,2400
|
93
93
|
oarepo_runtime/services/files/service.py,sha256=8DH0Pefr9kilM2JnOb-UYsnqerE8Z1Mu4p6DOJ4j_ZU,608
|
94
94
|
oarepo_runtime/services/relations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
95
95
|
oarepo_runtime/services/relations/components.py,sha256=3g0VdnGUM-2yYt50fPi-OADReBGJb4h05vmYHfh-QFs,592
|
96
96
|
oarepo_runtime/services/relations/errors.py,sha256=VtlOKq9MEUeJ4IsiZhY7lWoshrusA_RL4SOHe2titno,552
|
97
97
|
oarepo_runtime/services/relations/mapping.py,sha256=D7IYk83SXVgTv-0ohSnHOCzvCwbFLXJsayO1eQfQn0U,1285
|
98
|
-
oarepo_runtime/services/schema/__init__.py,sha256=
|
98
|
+
oarepo_runtime/services/schema/__init__.py,sha256=5u8wTvon4W6ODJNRJhRNChmQHAZTXwo6LV2mYRYs-EM,1377
|
99
99
|
oarepo_runtime/services/schema/cf.py,sha256=-m9seIH5VYUdxDsJlPVXS0-8f7xkpN7YfW1q9E1GacI,475
|
100
|
-
oarepo_runtime/services/schema/i18n.py,sha256
|
101
|
-
oarepo_runtime/services/schema/i18n_ui.py,sha256=
|
100
|
+
oarepo_runtime/services/schema/i18n.py,sha256=-lah_Xmm4zv1FA8Q7BFTZJjTZcZVcVfeFNvyzunMpIw,1686
|
101
|
+
oarepo_runtime/services/schema/i18n_ui.py,sha256=4abjHTrCl3SQDn0LKBwHGn2MFD9ivWSrzeKKwf94Z6U,2230
|
102
102
|
oarepo_runtime/services/schema/i18n_validation.py,sha256=fyMTi2Rw-KiHv7c7HN61zGxRVa9sAjAEEkAL5wUyKNo,236
|
103
103
|
oarepo_runtime/services/schema/marshmallow.py,sha256=LmcSxvbZ9jIhkNHCqqxt1SA2UNijoDmIzqli1MkoTrE,1153
|
104
|
-
oarepo_runtime/services/schema/oneofschema.py,sha256=
|
105
|
-
oarepo_runtime/services/schema/polymorphic.py,sha256=
|
104
|
+
oarepo_runtime/services/schema/oneofschema.py,sha256=GnWH4Or_G5M0NgSmCoqMI6PBrJg5AC9RHrcB5QDKRq0,6661
|
105
|
+
oarepo_runtime/services/schema/polymorphic.py,sha256=bAbUoTIeDBiJPYPhpLEKKZekEdkHlpqkmNxk1hN3PDw,564
|
106
106
|
oarepo_runtime/services/schema/ui.py,sha256=xQgW-zLyZoHldGw47uVtXQj-5LexVNKTholyq4MiBZo,3777
|
107
107
|
oarepo_runtime/services/schema/validation.py,sha256=fahqKGDdIYWux5ZeoljrEe8VD2fDZR9VpfvYmTYAmpw,1050
|
108
108
|
oarepo_runtime/translations/default_translations.py,sha256=060GBlA1ghWxfeumo6NqxCCZDb-6OezOuF6pr-_GEOQ,104
|
@@ -116,9 +116,9 @@ oarepo_runtime/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
|
|
116
116
|
oarepo_runtime/utils/functools.py,sha256=gKS9YZtlIYcDvdNA9cmYO00yjiXBYV1jg8VpcRUyQyg,1324
|
117
117
|
oarepo_runtime/utils/path.py,sha256=V1NVyk3m12_YLbj7QHYvUpE1wScO78bYsX1LOLeXDkI,3108
|
118
118
|
tests/pkg_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
119
|
-
oarepo_runtime-1.5.
|
120
|
-
oarepo_runtime-1.5.
|
121
|
-
oarepo_runtime-1.5.
|
122
|
-
oarepo_runtime-1.5.
|
123
|
-
oarepo_runtime-1.5.
|
124
|
-
oarepo_runtime-1.5.
|
119
|
+
oarepo_runtime-1.5.39.dist-info/LICENSE,sha256=h2uWz0OaB3EN-J1ImdGJZzc7yvfQjvHVYdUhQ-H7ypY,1064
|
120
|
+
oarepo_runtime-1.5.39.dist-info/METADATA,sha256=RGiou0J7zgp38I8Amo2FdSs2OejAezp8e3j5eqInPPg,4680
|
121
|
+
oarepo_runtime-1.5.39.dist-info/WHEEL,sha256=mguMlWGMX-VHnMpKOjjQidIo1ssRlCFu4a4mBpz1s2M,91
|
122
|
+
oarepo_runtime-1.5.39.dist-info/entry_points.txt,sha256=QrlXAKuPDVBinaSh_v3yO9_Nb9ZNmJCJ0VFcCW-z0Jg,327
|
123
|
+
oarepo_runtime-1.5.39.dist-info/top_level.txt,sha256=bHhlkT1_RQC4IkfTQCqA3iN4KCB6cSFQlsXpQMSP-bE,21
|
124
|
+
oarepo_runtime-1.5.39.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|