oarepo-runtime 1.5.36__py3-none-any.whl → 1.5.38__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.
@@ -0,0 +1,55 @@
1
+ import mimetypes
2
+ import os
3
+ from invenio_records_resources.services.files.components import FileServiceComponent
4
+ from marshmallow.exceptions import ValidationError
5
+
6
+ class AllowedFileTypesComponent(FileServiceComponent):
7
+
8
+ def guess_content_type(self, filename: str | None) -> str | None:
9
+ if filename:
10
+ return mimetypes.guess_type(filename)[0] or "application/octet-stream"
11
+ return None
12
+
13
+ @property
14
+ def allowed_mimetypes(self):
15
+ """Returns files attribute (field) key."""
16
+ return getattr(self.service.config, "allowed_mimetypes", [])
17
+
18
+ def guess_extension(self, file, mimetype):
19
+ """File extension."""
20
+ # The ``ext`` property is used to in search to aggregate file types, and we want e.g. both ``.jpeg`` and
21
+ # ``.jpg`` to be aggregated under ``.jpg``
22
+ ext_guessed = mimetypes.guess_extension(mimetype)
23
+
24
+ # 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
+ ):
29
+ return ext_guessed[1:]
30
+
31
+ # Support non-standard file extensions that cannot be guessed
32
+ _, ext = os.path.splitext(file)
33
+ if ext and len(ext) <= 5:
34
+ return ext[1:].lower()
35
+
36
+ if ext_guessed:
37
+ return ext_guessed[1:]
38
+
39
+ @property
40
+ def allowed_extensions(self):
41
+ """Returns files attribute (field) key."""
42
+ return getattr(self.service.config, "allowed_extensions", [])
43
+
44
+ def init_files(self, identity, id_, data, uow=None):
45
+ """Initialize the file upload for the record."""
46
+ list_files = list(data.files.entries)
47
+
48
+ for file in list_files:
49
+ allowed_type = self.guess_content_type(file)
50
+ allowed_ext = self.guess_extension(file, allowed_type)
51
+ if len(self.allowed_mimetypes) > 0 and allowed_type not in self.allowed_mimetypes:
52
+ raise ValidationError(f"Mimetype not supported, supported mimetypes: {self.allowed_mimetypes}")
53
+ elif len(self.allowed_extensions) > 0 and allowed_ext not in self.allowed_extensions:
54
+ raise ValidationError(f"Extension not supported, supported extensions: {self.allowed_extensions}")
55
+
@@ -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 SuggestQueryParser.factory(
118
- fields=fields,
119
- )
140
+ return FuzzySuggestQueryParser.factory(fields=fields)
120
141
 
121
142
 
122
143
  @dataclasses.dataclass
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: oarepo-runtime
3
- Version: 1.5.36
3
+ Version: 1.5.38
4
4
  Summary: A set of runtime extensions of Invenio repository
5
5
  Description-Content-Type: text/markdown
6
6
  License-File: LICENSE
@@ -71,7 +71,7 @@ oarepo_runtime/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
71
71
  oarepo_runtime/services/components.py,sha256=9wt9CmoCFA8Utbb8eNA-Mvzo5LCApHT9zHpWIWZNyXY,1506
72
72
  oarepo_runtime/services/generators.py,sha256=V582uA813AIXnFhzqUwakmDgBOI1SQe3XZeJtUXNbwM,872
73
73
  oarepo_runtime/services/results.py,sha256=ocEXdTl1Gdu-OmAkmB98Yf5t4IwsbESDf1r3GV73FTg,2706
74
- oarepo_runtime/services/search.py,sha256=ywfwGH7oAM44WeOSjlIsY_qoCMZJ1TlTLd_NgE2ow3Y,5296
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,6 +89,7 @@ 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=yQpZ0rCaIUkECPZMZ4aH2m1NIRlEWPgiPPV_6yUoPbY,2272
92
93
  oarepo_runtime/services/files/service.py,sha256=8DH0Pefr9kilM2JnOb-UYsnqerE8Z1Mu4p6DOJ4j_ZU,608
93
94
  oarepo_runtime/services/relations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
94
95
  oarepo_runtime/services/relations/components.py,sha256=3g0VdnGUM-2yYt50fPi-OADReBGJb4h05vmYHfh-QFs,592
@@ -115,9 +116,9 @@ oarepo_runtime/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
115
116
  oarepo_runtime/utils/functools.py,sha256=gKS9YZtlIYcDvdNA9cmYO00yjiXBYV1jg8VpcRUyQyg,1324
116
117
  oarepo_runtime/utils/path.py,sha256=V1NVyk3m12_YLbj7QHYvUpE1wScO78bYsX1LOLeXDkI,3108
117
118
  tests/pkg_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
118
- oarepo_runtime-1.5.36.dist-info/LICENSE,sha256=h2uWz0OaB3EN-J1ImdGJZzc7yvfQjvHVYdUhQ-H7ypY,1064
119
- oarepo_runtime-1.5.36.dist-info/METADATA,sha256=yFDeGezqfZiK4mOLv_wBTHC75fBdmI2K4R7anq3fr34,4680
120
- oarepo_runtime-1.5.36.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
121
- oarepo_runtime-1.5.36.dist-info/entry_points.txt,sha256=QrlXAKuPDVBinaSh_v3yO9_Nb9ZNmJCJ0VFcCW-z0Jg,327
122
- oarepo_runtime-1.5.36.dist-info/top_level.txt,sha256=bHhlkT1_RQC4IkfTQCqA3iN4KCB6cSFQlsXpQMSP-bE,21
123
- oarepo_runtime-1.5.36.dist-info/RECORD,,
119
+ oarepo_runtime-1.5.38.dist-info/LICENSE,sha256=h2uWz0OaB3EN-J1ImdGJZzc7yvfQjvHVYdUhQ-H7ypY,1064
120
+ oarepo_runtime-1.5.38.dist-info/METADATA,sha256=9jbrRNAbeANj8jeFjvvqXPethvs0SoHPechzSEdX7Rs,4680
121
+ oarepo_runtime-1.5.38.dist-info/WHEEL,sha256=mguMlWGMX-VHnMpKOjjQidIo1ssRlCFu4a4mBpz1s2M,91
122
+ oarepo_runtime-1.5.38.dist-info/entry_points.txt,sha256=QrlXAKuPDVBinaSh_v3yO9_Nb9ZNmJCJ0VFcCW-z0Jg,327
123
+ oarepo_runtime-1.5.38.dist-info/top_level.txt,sha256=bHhlkT1_RQC4IkfTQCqA3iN4KCB6cSFQlsXpQMSP-bE,21
124
+ oarepo_runtime-1.5.38.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (70.1.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5