oarepo-runtime 1.10.3__py3-none-any.whl → 2.0.0.dev4__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.
Files changed (171) hide show
  1. oarepo_runtime/__init__.py +24 -0
  2. oarepo_runtime/api.py +210 -0
  3. oarepo_runtime/cli/__init__.py +10 -21
  4. oarepo_runtime/cli/search.py +34 -0
  5. oarepo_runtime/config.py +98 -13
  6. oarepo_runtime/ext.py +64 -82
  7. oarepo_runtime/proxies.py +21 -5
  8. oarepo_runtime/records/__init__.py +11 -50
  9. oarepo_runtime/records/drafts.py +24 -18
  10. oarepo_runtime/records/mapping.py +84 -0
  11. oarepo_runtime/records/pid_providers.py +43 -7
  12. oarepo_runtime/records/systemfields/__init__.py +15 -33
  13. oarepo_runtime/records/systemfields/mapping.py +41 -24
  14. oarepo_runtime/records/systemfields/publication_status.py +61 -0
  15. oarepo_runtime/services/__init__.py +12 -0
  16. oarepo_runtime/services/config/__init__.py +15 -21
  17. oarepo_runtime/services/config/link_conditions.py +69 -75
  18. oarepo_runtime/services/config/permissions.py +62 -0
  19. oarepo_runtime/services/facets/__init__.py +12 -33
  20. oarepo_runtime/services/facets/params.py +45 -110
  21. oarepo_runtime/services/records/__init__.py +14 -1
  22. oarepo_runtime/services/records/links.py +21 -11
  23. oarepo_runtime/services/records/mapping.py +42 -0
  24. oarepo_runtime/services/results.py +98 -109
  25. oarepo_runtime/services/schema/__init__.py +12 -44
  26. oarepo_runtime/services/schema/i18n.py +47 -22
  27. oarepo_runtime/services/schema/i18n_ui.py +61 -24
  28. {oarepo_runtime-1.10.3.dist-info → oarepo_runtime-2.0.0.dev4.dist-info}/METADATA +10 -21
  29. oarepo_runtime-2.0.0.dev4.dist-info/RECORD +32 -0
  30. {oarepo_runtime-1.10.3.dist-info → oarepo_runtime-2.0.0.dev4.dist-info}/WHEEL +1 -2
  31. oarepo_runtime-2.0.0.dev4.dist-info/entry_points.txt +5 -0
  32. oarepo_runtime/cli/assets.py +0 -145
  33. oarepo_runtime/cli/base.py +0 -25
  34. oarepo_runtime/cli/cf.py +0 -15
  35. oarepo_runtime/cli/check.py +0 -167
  36. oarepo_runtime/cli/configuration.py +0 -51
  37. oarepo_runtime/cli/fixtures.py +0 -167
  38. oarepo_runtime/cli/index.py +0 -272
  39. oarepo_runtime/cli/permissions/__init__.py +0 -6
  40. oarepo_runtime/cli/permissions/base.py +0 -26
  41. oarepo_runtime/cli/permissions/evaluate.py +0 -63
  42. oarepo_runtime/cli/permissions/list.py +0 -239
  43. oarepo_runtime/cli/permissions/search.py +0 -121
  44. oarepo_runtime/cli/validate.py +0 -150
  45. oarepo_runtime/datastreams/__init__.py +0 -38
  46. oarepo_runtime/datastreams/asynchronous.py +0 -247
  47. oarepo_runtime/datastreams/catalogue.py +0 -150
  48. oarepo_runtime/datastreams/datastreams.py +0 -152
  49. oarepo_runtime/datastreams/errors.py +0 -54
  50. oarepo_runtime/datastreams/ext.py +0 -41
  51. oarepo_runtime/datastreams/fixtures.py +0 -265
  52. oarepo_runtime/datastreams/json.py +0 -4
  53. oarepo_runtime/datastreams/readers/__init__.py +0 -39
  54. oarepo_runtime/datastreams/readers/attachments.py +0 -51
  55. oarepo_runtime/datastreams/readers/excel.py +0 -123
  56. oarepo_runtime/datastreams/readers/json.py +0 -27
  57. oarepo_runtime/datastreams/readers/service.py +0 -54
  58. oarepo_runtime/datastreams/readers/yaml.py +0 -14
  59. oarepo_runtime/datastreams/semi_asynchronous.py +0 -91
  60. oarepo_runtime/datastreams/synchronous.py +0 -70
  61. oarepo_runtime/datastreams/transformers.py +0 -18
  62. oarepo_runtime/datastreams/types.py +0 -323
  63. oarepo_runtime/datastreams/utils.py +0 -131
  64. oarepo_runtime/datastreams/writers/__init__.py +0 -21
  65. oarepo_runtime/datastreams/writers/attachments_file.py +0 -92
  66. oarepo_runtime/datastreams/writers/attachments_service.py +0 -118
  67. oarepo_runtime/datastreams/writers/publish.py +0 -70
  68. oarepo_runtime/datastreams/writers/service.py +0 -175
  69. oarepo_runtime/datastreams/writers/utils.py +0 -30
  70. oarepo_runtime/datastreams/writers/validation_errors.py +0 -20
  71. oarepo_runtime/datastreams/writers/yaml.py +0 -56
  72. oarepo_runtime/ext_config.py +0 -67
  73. oarepo_runtime/i18n/__init__.py +0 -3
  74. oarepo_runtime/info/__init__.py +0 -0
  75. oarepo_runtime/info/check.py +0 -95
  76. oarepo_runtime/info/permissions/__init__.py +0 -0
  77. oarepo_runtime/info/permissions/debug.py +0 -191
  78. oarepo_runtime/info/views.py +0 -586
  79. oarepo_runtime/profile.py +0 -60
  80. oarepo_runtime/records/dumpers/__init__.py +0 -8
  81. oarepo_runtime/records/dumpers/edtf_interval.py +0 -38
  82. oarepo_runtime/records/dumpers/multilingual_dumper.py +0 -34
  83. oarepo_runtime/records/entity_resolvers/__init__.py +0 -13
  84. oarepo_runtime/records/entity_resolvers/proxies.py +0 -57
  85. oarepo_runtime/records/mappings/__init__.py +0 -0
  86. oarepo_runtime/records/mappings/rdm_parent_mapping.json +0 -483
  87. oarepo_runtime/records/owners/__init__.py +0 -3
  88. oarepo_runtime/records/owners/registry.py +0 -22
  89. oarepo_runtime/records/relations/__init__.py +0 -22
  90. oarepo_runtime/records/relations/base.py +0 -296
  91. oarepo_runtime/records/relations/internal.py +0 -46
  92. oarepo_runtime/records/relations/lookup.py +0 -28
  93. oarepo_runtime/records/relations/pid_relation.py +0 -102
  94. oarepo_runtime/records/systemfields/featured_file.py +0 -45
  95. oarepo_runtime/records/systemfields/has_draftcheck.py +0 -47
  96. oarepo_runtime/records/systemfields/icu.py +0 -371
  97. oarepo_runtime/records/systemfields/owner.py +0 -115
  98. oarepo_runtime/records/systemfields/record_status.py +0 -35
  99. oarepo_runtime/records/systemfields/selectors.py +0 -98
  100. oarepo_runtime/records/systemfields/synthetic.py +0 -130
  101. oarepo_runtime/resources/__init__.py +0 -4
  102. oarepo_runtime/resources/config.py +0 -12
  103. oarepo_runtime/resources/file_resource.py +0 -15
  104. oarepo_runtime/resources/json_serializer.py +0 -27
  105. oarepo_runtime/resources/localized_ui_json_serializer.py +0 -54
  106. oarepo_runtime/resources/resource.py +0 -53
  107. oarepo_runtime/resources/responses.py +0 -20
  108. oarepo_runtime/services/components.py +0 -429
  109. oarepo_runtime/services/config/draft_link.py +0 -23
  110. oarepo_runtime/services/config/permissions_presets.py +0 -174
  111. oarepo_runtime/services/config/service.py +0 -117
  112. oarepo_runtime/services/custom_fields/__init__.py +0 -80
  113. oarepo_runtime/services/custom_fields/mappings.py +0 -188
  114. oarepo_runtime/services/entity/__init__.py +0 -0
  115. oarepo_runtime/services/entity/config.py +0 -14
  116. oarepo_runtime/services/entity/schema.py +0 -9
  117. oarepo_runtime/services/entity/service.py +0 -48
  118. oarepo_runtime/services/expansions/__init__.py +0 -0
  119. oarepo_runtime/services/expansions/expandable_fields.py +0 -21
  120. oarepo_runtime/services/expansions/service.py +0 -4
  121. oarepo_runtime/services/facets/base.py +0 -12
  122. oarepo_runtime/services/facets/date.py +0 -72
  123. oarepo_runtime/services/facets/enum.py +0 -11
  124. oarepo_runtime/services/facets/facet_groups_names.py +0 -17
  125. oarepo_runtime/services/facets/max_facet.py +0 -13
  126. oarepo_runtime/services/facets/multilingual_facet.py +0 -33
  127. oarepo_runtime/services/facets/nested_facet.py +0 -32
  128. oarepo_runtime/services/facets/year_histogram.py +0 -200
  129. oarepo_runtime/services/files/__init__.py +0 -8
  130. oarepo_runtime/services/files/components.py +0 -62
  131. oarepo_runtime/services/files/service.py +0 -16
  132. oarepo_runtime/services/generators.py +0 -10
  133. oarepo_runtime/services/permissions/__init__.py +0 -3
  134. oarepo_runtime/services/permissions/generators.py +0 -103
  135. oarepo_runtime/services/relations/__init__.py +0 -0
  136. oarepo_runtime/services/relations/components.py +0 -15
  137. oarepo_runtime/services/relations/errors.py +0 -18
  138. oarepo_runtime/services/relations/mapping.py +0 -38
  139. oarepo_runtime/services/schema/cf.py +0 -13
  140. oarepo_runtime/services/schema/i18n_validation.py +0 -7
  141. oarepo_runtime/services/schema/marshmallow.py +0 -44
  142. oarepo_runtime/services/schema/marshmallow_to_json_schema.py +0 -72
  143. oarepo_runtime/services/schema/oneofschema.py +0 -192
  144. oarepo_runtime/services/schema/polymorphic.py +0 -21
  145. oarepo_runtime/services/schema/rdm.py +0 -146
  146. oarepo_runtime/services/schema/rdm_ui.py +0 -156
  147. oarepo_runtime/services/schema/ui.py +0 -251
  148. oarepo_runtime/services/schema/validation.py +0 -70
  149. oarepo_runtime/services/search.py +0 -282
  150. oarepo_runtime/services/service.py +0 -61
  151. oarepo_runtime/tasks.py +0 -6
  152. oarepo_runtime/translations/cs/LC_MESSAGES/messages.mo +0 -0
  153. oarepo_runtime/translations/cs/LC_MESSAGES/messages.po +0 -95
  154. oarepo_runtime/translations/default_translations.py +0 -6
  155. oarepo_runtime/translations/en/LC_MESSAGES/messages.mo +0 -0
  156. oarepo_runtime/translations/en/LC_MESSAGES/messages.po +0 -97
  157. oarepo_runtime/translations/messages.pot +0 -100
  158. oarepo_runtime/uow.py +0 -146
  159. oarepo_runtime/utils/__init__.py +0 -0
  160. oarepo_runtime/utils/functools.py +0 -37
  161. oarepo_runtime/utils/identity_utils.py +0 -35
  162. oarepo_runtime/utils/index.py +0 -11
  163. oarepo_runtime/utils/path.py +0 -97
  164. oarepo_runtime-1.10.3.dist-info/RECORD +0 -163
  165. oarepo_runtime-1.10.3.dist-info/entry_points.txt +0 -16
  166. oarepo_runtime-1.10.3.dist-info/top_level.txt +0 -2
  167. tests/marshmallow_to_json/__init__.py +0 -0
  168. tests/marshmallow_to_json/test_datacite_ui_schema.py +0 -1410
  169. tests/marshmallow_to_json/test_simple_schema.py +0 -52
  170. tests/pkg_data/__init__.py +0 -0
  171. {oarepo_runtime-1.10.3.dist-info → oarepo_runtime-2.0.0.dev4.dist-info}/licenses/LICENSE +0 -0
@@ -1,32 +0,0 @@
1
- from invenio_search.engine import dsl
2
-
3
-
4
- class NestedLabeledFacet(dsl.Facet):
5
- agg_type = "nested"
6
-
7
- def __init__(self, path, nested_facet, label=""):
8
- self._path = path
9
- self._inner = nested_facet
10
- self._label = label
11
- super(NestedLabeledFacet, self).__init__(
12
- path=path,
13
- aggs={
14
- "inner": nested_facet.get_aggregation(),
15
- },
16
- )
17
-
18
- def get_values(self, data, filter_values):
19
- return self._inner.get_values(data.inner, filter_values)
20
-
21
- def add_filter(self, filter_values):
22
- inner_q = self._inner.add_filter(filter_values)
23
- if inner_q:
24
- return dsl.Nested(path=self._path, query=inner_q)
25
-
26
- def get_labelled_values(self, data, filter_values):
27
- """Get a labelled version of a bucket."""
28
- try:
29
- out = data["buckets"]
30
- except KeyError:
31
- out = []
32
- return {"buckets": out, "label": str(self._label)}
@@ -1,200 +0,0 @@
1
- import re
2
- from typing import Dict, List
3
-
4
- from invenio_records_resources.services.records.facets.facets import LabelledFacetMixin
5
- from invenio_search.engine import dsl
6
-
7
-
8
- class YearAutoHistogramFacet(LabelledFacetMixin, dsl.Facet):
9
- """Histogram facet.
10
-
11
- .. code-block:: python
12
-
13
- facets = {
14
- 'year': IntegerHistogramFacet(
15
- field='year',
16
- label=_('Year'),
17
- size=1000000
18
- )
19
- }
20
-
21
- Usage in the oarepo model together with SyntheticSystemField::
22
- record:
23
- record:
24
- imports:
25
- - import: oarepo_runtime.records.systemfields.SyntheticSystemField
26
- - import: oarepo_runtime.records.systemfields.PathSelector
27
- fields:
28
- year: |
29
- SyntheticSystemField(
30
- selector=PathSelector("metadata.date"),
31
- key="year",
32
- filter=lambda x: len(x) >= 4,
33
- map=lambda x: x[:4]
34
- )
35
- properties:
36
- year:
37
- facets:
38
- facet-class: oarepo_runtime.services.facets.year_histogram.YearAutoHistogramFacet
39
- type: edtf
40
- """
41
-
42
- agg_type = "auto_date_histogram"
43
-
44
- def __init__(self, **kwargs):
45
- self._min_doc_count = kwargs.pop("min_doc_count", 0)
46
- buckets = kwargs.pop("buckets", 20)
47
- # TODO: the minimum interval should be year, but opensearch does not support it yet
48
- super().__init__(
49
- **kwargs, buckets=buckets, format="yyyy", minimum_interval="month"
50
- )
51
-
52
- def get_value_filter(self, filter_value):
53
- if "/" in filter_value:
54
- start, end = filter_value.split("/")
55
- return dsl.query.Range(
56
- _expand__to_dot=False,
57
- **{
58
- self._params["field"]: {
59
- "gte": f"{start}-01-01",
60
- "lte": f"{end}-12-31",
61
- }
62
- },
63
- )
64
- return dsl.query.Term(
65
- _expand__to_dot=False,
66
- **{
67
- self._params["field"]: {
68
- "gte": f"{filter_value}-01-01",
69
- "lte": f"{filter_value}-12-31",
70
- }
71
- },
72
- )
73
-
74
- def add_filter(self, filter_values):
75
- ret = super().add_filter(filter_values)
76
- return ret
77
-
78
- def get_labelled_values(self, data, filter_values):
79
- """Get a labelled version of a bucket."""
80
-
81
- # fix for opensearch bug
82
- data = self.fix_yearly_interval(data)
83
-
84
- interval = data["interval"]
85
-
86
- interval_in_years = int(re.sub(r"\D", "", interval))
87
-
88
- buckets = data["buckets"]
89
-
90
- for bucket in buckets:
91
- bucket["interval"] = interval_in_years
92
-
93
- if self._min_doc_count > 0:
94
- buckets = self._merge_small_buckets(buckets)
95
-
96
- out_buckets = []
97
- for i, bucket in enumerate(buckets):
98
- value = int(bucket["key_as_string"].split("-")[0])
99
-
100
- out_buckets.append(
101
- {
102
- **bucket,
103
- "interval": f"{bucket['interval']}y",
104
- "start": str(value),
105
- }
106
- )
107
- if i > 0:
108
- out_buckets[i - 1]["end"] = str(value - 1)
109
-
110
- if out_buckets:
111
- out_buckets[-1]["end"] = str(
112
- int(out_buckets[-1]["start"]) + interval_in_years - 1
113
- )
114
-
115
- return {
116
- "buckets": out_buckets,
117
- "label": str(self._label),
118
- "interval": interval,
119
- }
120
-
121
- def merge_buckets(self, buckets):
122
- merged = {}
123
-
124
- for bucket in buckets:
125
- key = bucket["key_as_string"]
126
- if key not in merged:
127
- merged[key] = {
128
- "key_as_string": key,
129
- "key": bucket["key"],
130
- "doc_count": 0,
131
- }
132
-
133
- merged[key]["doc_count"] += bucket["doc_count"]
134
-
135
- result = list(merged.values())
136
- return result
137
-
138
- def fix_yearly_interval(self, data) -> Dict:
139
- """
140
- Currently opensearch has a bug that does not allow to set minimum_interval to year.
141
- This function will fix the interval to be yearly if the minimum_interval is has lower value.
142
- """
143
- data = data.to_dict()
144
-
145
- interval = data["interval"]
146
-
147
- if interval.endswith("y"):
148
- # no need to fix the interval, as it is in years
149
- return data
150
-
151
- # make sure it is in years
152
- data["interval"] = "1y"
153
-
154
- buckets = data["buckets"]
155
- data["buckets"] = out_buckets = []
156
-
157
- by_year = {}
158
-
159
- # there might be several buckets returned with the same year - merge them
160
- for bucket in buckets:
161
- key = bucket["key_as_string"]
162
- if key not in by_year:
163
- by_year[key] = {
164
- "key_as_string": key,
165
- "key": bucket["key"],
166
- "doc_count": 0,
167
- }
168
- out_buckets.append(by_year[key])
169
-
170
- by_year[key]["doc_count"] += bucket["doc_count"]
171
-
172
- return data
173
-
174
- def _merge_small_buckets(self, buckets: List[Dict]):
175
- """
176
- Merges small buckets into the previous bucket. If the small bucket is the first one,
177
- merge it with subsequent buckets until the first non-small bucket is found.
178
- """
179
- ret = []
180
- initial_small_buckets = 0
181
- initial_small_interval = 0
182
- for bucket in buckets:
183
- if bucket["doc_count"] < self._min_doc_count:
184
- if ret:
185
- ret[-1]["doc_count"] += bucket["doc_count"]
186
- ret[-1]["interval"] += bucket["interval"]
187
- else:
188
- initial_small_buckets += bucket["doc_count"]
189
- initial_small_interval += bucket["interval"]
190
- else:
191
- ret.append(bucket)
192
-
193
- if ret and initial_small_buckets:
194
- doc_count = ret[0]["doc_count"] + initial_small_buckets
195
- interval = ret[0]["interval"] + initial_small_interval
196
- ret[0] = buckets[0]
197
- ret[0]["doc_count"] = doc_count
198
- ret[0]["interval"] = interval
199
-
200
- return ret
@@ -1,8 +0,0 @@
1
- try:
2
- from invenio_records_resources.services.records.components import (
3
- FilesOptionsComponent as FilesComponent,
4
- )
5
- except ImportError:
6
- from invenio_records_resources.services.records.components import FilesComponent
7
-
8
- __all__ = ("FilesComponent",)
@@ -1,62 +0,0 @@
1
- import mimetypes
2
- import os
3
-
4
- from invenio_records_resources.services.files.components import FileServiceComponent
5
- from marshmallow.exceptions import ValidationError
6
-
7
-
8
- class AllowedFileTypesComponent(FileServiceComponent):
9
- def guess_content_type(self, filename: str | None) -> str | None:
10
- if filename:
11
- return mimetypes.guess_type(filename)[0] or "application/octet-stream"
12
- return None
13
-
14
- @property
15
- def allowed_mimetypes(self):
16
- """Returns files attribute (field) key."""
17
- return getattr(self.service.config, "allowed_mimetypes", [])
18
-
19
- def guess_extension(self, file, mimetype):
20
- """File extension."""
21
- # The ``ext`` property is used to in search to aggregate file types, and we want e.g. both ``.jpeg`` and
22
- # ``.jpg`` to be aggregated under ``.jpg``
23
- ext_guessed = mimetypes.guess_extension(mimetype)
24
-
25
- # Check if a valid extension is guessed and it's not the default mimetype
26
- if ext_guessed is not None and mimetype != "application/octet-stream":
27
- return ext_guessed[1:]
28
-
29
- # Support non-standard file extensions that cannot be guessed
30
- _, ext = os.path.splitext(file)
31
- if ext and len(ext) <= 5:
32
- return ext[1:].lower()
33
-
34
- if ext_guessed:
35
- return ext_guessed[1:]
36
-
37
- @property
38
- def allowed_extensions(self):
39
- """Returns files attribute (field) key."""
40
- return getattr(self.service.config, "allowed_extensions", [])
41
-
42
- def init_files(self, identity, id_, data, uow=None):
43
- """Initialize the file upload for the record."""
44
- list_files = list(data.files.entries)
45
-
46
- for file in list_files:
47
- allowed_type = self.guess_content_type(file)
48
- allowed_ext = self.guess_extension(file, allowed_type)
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
- )
@@ -1,16 +0,0 @@
1
- from invenio_records_resources.services.uow import unit_of_work
2
-
3
- from oarepo_runtime.datastreams.utils import get_record_service_for_file_service
4
-
5
-
6
- class FeaturedFileServiceMixin:
7
- @unit_of_work()
8
- def commit_file(self, identity, id_, file_key, uow=None):
9
- super().commit_file(identity, id_, file_key, uow=uow)
10
-
11
- record = self._get_record(id_, identity, "read", file_key=file_key)
12
- record_service = get_record_service_for_file_service(self, record=record)
13
- indexer = record_service.indexer
14
- if indexer:
15
- indexer.index(record)
16
- indexer.refresh()
@@ -1,10 +0,0 @@
1
- import warnings
2
-
3
- from .permissions import RecordOwners
4
-
5
- warnings.warn(
6
- "oarepo_runtime.services.generators is deprecated, import RecordOwners from "
7
- "oarepo_runtime.services.permissions",
8
- DeprecationWarning,
9
- )
10
- __all__ = ("RecordOwners",)
@@ -1,3 +0,0 @@
1
- from .generators import IfDraftType, RecordOwners, UserWithRole
2
-
3
- __all__ = ("RecordOwners", "UserWithRole", "IfDraftType")
@@ -1,103 +0,0 @@
1
- from typing import Literal
2
-
3
- from flask import current_app
4
- from flask_principal import RoleNeed, UserNeed
5
- from invenio_records_permissions.generators import (
6
- ConditionalGenerator,
7
- Disable,
8
- Generator,
9
- )
10
- from invenio_search.engine import dsl
11
-
12
-
13
- class RecordOwners(Generator):
14
- """Allows record owners."""
15
-
16
- def needs(self, record=None, **kwargs):
17
- """Enabling Needs."""
18
- if record is None:
19
- # 'record' is required, so if not passed we default to empty array,
20
- # i.e. superuser-access.
21
- return []
22
- if current_app.config.get("INVENIO_RDM_ENABLED", False):
23
- owners = getattr(record.parent.access, "owned_by", None)
24
- if owners is not None:
25
- owners_list = owners if isinstance(owners, list) else [owners]
26
- return [UserNeed(owner.owner_id) for owner in owners_list]
27
- else:
28
- owners = getattr(record.parent, "owners", None)
29
- if owners is not None:
30
- return [UserNeed(owner.id) for owner in owners]
31
- return []
32
-
33
- def query_filter(self, identity=None, **kwargs):
34
- """Filters for current identity as owner."""
35
- users = [n.value for n in identity.provides if n.method == "id"]
36
- if users:
37
- if current_app.config.get("INVENIO_RDM_ENABLED", False):
38
- return dsl.Q("terms", **{"parent.access.owned_by.user": users})
39
- else:
40
- return dsl.Q("terms", **{"parent.owners.user": users})
41
- return dsl.Q("match_none")
42
-
43
-
44
- class UserWithRole(Generator):
45
- def __init__(self, *roles):
46
- self.roles = roles
47
-
48
- def needs(self, **kwargs):
49
- return [RoleNeed(role) for role in self.roles]
50
-
51
- def query_filter(self, identity=None, **kwargs):
52
- if not identity:
53
- return dsl.Q("match_none")
54
- for provide in identity.provides:
55
- if provide.method == "role" and provide.value in self.roles:
56
- return dsl.Q("match_all")
57
- return dsl.Q("match_none")
58
-
59
-
60
- class IfDraftType(ConditionalGenerator):
61
- def __init__(
62
- self,
63
- draft_types: (
64
- list[Literal["initial"] | Literal["metadata"] | Literal["new_version"]]
65
- | Literal["initial"]
66
- | Literal["metadata"]
67
- | Literal["new_version"]
68
- ),
69
- then_=None,
70
- else_=None,
71
- ):
72
- if not isinstance(draft_types, (list, tuple)):
73
- draft_types = [draft_types]
74
- self._draft_types = draft_types
75
- if not then_:
76
- then_ = [Disable()]
77
- if not else_:
78
- else_ = [Disable()]
79
- if not isinstance(then_, (list, tuple)):
80
- then_ = [then_]
81
- if not isinstance(else_, (list, tuple)):
82
- else_ = [else_]
83
- super().__init__(then_, else_)
84
-
85
- def _condition(self, record=None, **kwargs):
86
- if not record:
87
- return False
88
-
89
- index = record.versions.index
90
- is_latest = record.versions.is_latest
91
- is_draft = record.is_draft
92
-
93
- if not is_draft:
94
- return False
95
-
96
- if index == 1 and not is_latest:
97
- draft_type = "initial"
98
- elif index > 1 and not is_latest:
99
- draft_type = "new_version"
100
- else:
101
- draft_type = "metadata"
102
-
103
- return draft_type in self._draft_types
File without changes
@@ -1,15 +0,0 @@
1
- from invenio_records_resources.services.records.components import ServiceComponent
2
-
3
- from oarepo_runtime.uow import CachingUnitOfWork
4
-
5
-
6
- class CachingRelationsComponent(ServiceComponent):
7
- def create(self, identity, *, record, **kwargs):
8
- """Create handler."""
9
- # skutecny jmeno relations atributu
10
- if isinstance(self.uow, CachingUnitOfWork) and hasattr(record, "relations"):
11
- record.relations.set_cache(self.uow.cache)
12
-
13
- def update(self, identity, *, record, **kwargs):
14
- """Update handler."""
15
- self.create(identity, record=record, **kwargs)
@@ -1,18 +0,0 @@
1
- class InvalidRelationError(KeyError):
2
- def __init__(self, message, related_id, location):
3
- self.related_id = related_id
4
- self.location = location
5
- super().__init__(message)
6
-
7
-
8
- class MultipleInvalidRelationErrors(Exception):
9
- """
10
- Records multiple validation errors of a relation field.
11
- self.errors is a list of pairs (path, Error)
12
- """
13
-
14
- def __init__(self, errors):
15
- super().__init__(
16
- "; ".join([f"{e[0]}: {type(e[1]).__name__}({e[1]})" for e in errors])
17
- )
18
- self.errors = errors
@@ -1,38 +0,0 @@
1
- class RelationsMapping:
2
- """Helper class for managing relation fields."""
3
-
4
- def __init__(self, record, fields):
5
- """Initialize the relations mapping."""
6
- # Needed because we overwrite __setattr__
7
- cache = {}
8
- self._fields = fields
9
- for name, fld in fields.items():
10
- field_value = fld.get_value(record, cache)
11
- setattr(self, name, field_value)
12
-
13
- def __iter__(self):
14
- """Iterate over the relations fields."""
15
- return iter(self._fields)
16
-
17
- def validate(self, fields=None):
18
- """Validates all relations in the record."""
19
- for name in fields or self:
20
- getattr(self, name).validate()
21
-
22
- def dereference(self, fields=None):
23
- """Dereferences relation fields."""
24
- for name in fields or self:
25
- getattr(self, name).dereference()
26
-
27
- def clean(self, fields=None):
28
- """Clean dereferenced relation fields."""
29
- for name in fields or self:
30
- getattr(self, name).clean()
31
-
32
- def set_cache(self, cache):
33
- from oarepo_runtime.records.relations import PIDRelation
34
-
35
- for key, fld in self._fields.items():
36
- if isinstance(fld, PIDRelation):
37
- fld.cache = cache
38
- getattr(self, key).cache = cache
@@ -1,13 +0,0 @@
1
- from invenio_records_resources.services.custom_fields.schema import (
2
- CustomFieldsSchemaUI as InvenioCustomFieldsSchemaUI,
3
- )
4
-
5
-
6
- class CustomFieldsSchemaUI(InvenioCustomFieldsSchemaUI):
7
- def _serialize(self, obj, **kwargs):
8
- self._schema.context.update(self.context)
9
- return super()._serialize(obj, **kwargs)
10
-
11
- def _deserialize(self, data, **kwargs):
12
- self._schema.context.update(self.context)
13
- return super()._deserialize(data, **kwargs)
@@ -1,7 +0,0 @@
1
- import langcodes
2
- from marshmallow.exceptions import ValidationError
3
-
4
-
5
- def lang_code_validator(value):
6
- if value != "_" and not langcodes.Language.get(value).is_valid():
7
- raise ValidationError(f"Invalid language code {value}")
@@ -1,44 +0,0 @@
1
- import typing
2
-
3
- from invenio_rdm_records.services.schemas.record import RDMRecordSchema
4
- from invenio_records_resources.services.records.schema import (
5
- BaseRecordSchema as InvenioBaseRecordSchema,
6
- )
7
-
8
- import marshmallow as ma
9
-
10
-
11
- class BaseRecordSchema(InvenioBaseRecordSchema):
12
- """Base record schema - in addition to invenio exposes $schema as well."""
13
-
14
- _schema = ma.fields.Str(attribute="$schema", data_key="$schema")
15
-
16
-
17
- class RDMBaseRecordSchema(RDMRecordSchema):
18
- """Base record schema - in addition to invenio exposes $schema as well."""
19
-
20
- _schema = ma.fields.Str(attribute="$schema", data_key="$schema")
21
-
22
-
23
- class DictOnlySchema(ma.Schema):
24
- def get_attribute(self, obj: typing.Any, attr: str, default: typing.Any):
25
- if not isinstance(attr, int) and "." in attr:
26
- return _get_value_for_keys_dict_only(obj, attr.split("."), default)
27
- else:
28
- return _get_value_for_key_dict_only(obj, attr, default)
29
-
30
-
31
- def _get_value_for_keys_dict_only(obj, keys, default):
32
- if len(keys) == 1:
33
- return _get_value_for_key_dict_only(obj, keys[0], default)
34
- else:
35
- return _get_value_for_keys_dict_only(
36
- _get_value_for_key_dict_only(obj, keys[0], default), keys[1:], default
37
- )
38
-
39
-
40
- def _get_value_for_key_dict_only(obj, key, default):
41
- try:
42
- return obj[key]
43
- except (KeyError, IndexError, TypeError, AttributeError):
44
- return default
@@ -1,72 +0,0 @@
1
- from marshmallow import Schema, fields
2
- from oarepo_runtime.services.schema.ui import (
3
- LocalizedEDTFTime,
4
- LocalizedDateTime,
5
- LocalizedEDTF,
6
- LocalizedEDTFInterval,
7
- LocalizedEDTFTimeInterval,
8
- LocalizedTime
9
- )
10
-
11
- field_type_converters = {
12
- fields.String : lambda field: {"type" : "string"},
13
- fields.Integer: lambda field: {"type": "integer"},
14
- fields.Float: lambda field: {"type": "number"},
15
- fields.Boolean: lambda field: {"type": "boolean"},
16
- fields.List: lambda field: {
17
- "type": "array",
18
- "items": convert_field_to_json_schema(field.inner)
19
- },
20
- fields.Nested: lambda field: {
21
- "type": "object",
22
- "properties": marshmallow_to_json_schema(field.schema)["properties"]
23
- },
24
- fields.Raw: lambda field: {
25
- "type": "object",
26
- 'additionalProperties' : True
27
- },
28
- LocalizedEDTFTime: lambda field: {
29
- "type": "string",
30
- "format": "date-time",
31
- },
32
- LocalizedDateTime: lambda field: {
33
- "type": "string",
34
- "format": "date-time",
35
- },
36
- LocalizedTime: lambda field: {
37
- "type": "string",
38
- "format": "time",
39
- },
40
- LocalizedEDTF: lambda field: {
41
- "type": "string",
42
- "format": "date",
43
- },
44
- LocalizedEDTFInterval: lambda field: {
45
- "type": "string",
46
- "format": "date-time",
47
- },
48
- LocalizedEDTFTimeInterval: lambda field: {
49
- "type": "string",
50
- "format": "date-time",
51
- }
52
- }
53
-
54
- def marshmallow_to_json_schema(schema:Schema) -> dict:
55
- json_schema = {
56
- 'type': 'object',
57
- 'properties': {}
58
- }
59
-
60
- for field_name, field in schema.fields.items():
61
- json_schema["properties"][field_name] = convert_field_to_json_schema(field)
62
-
63
- return json_schema
64
-
65
-
66
- def convert_field_to_json_schema(field:fields) -> dict:
67
- for field_type in type(field).mro():
68
- if field_type in field_type_converters:
69
- return field_type_converters[field_type](field)
70
-
71
- # no converter found, just string
72
- return {"type":"string"}