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,296 +0,0 @@
1
- from functools import cached_property
2
- from typing import List
3
-
4
- from invenio_records.dictutils import dict_lookup, dict_set
5
- from invenio_records.systemfields.base import SystemField
6
- from invenio_records.systemfields.relations import (
7
- InvalidCheckValue,
8
- InvalidRelationValue,
9
- )
10
-
11
- from oarepo_runtime.services.relations.errors import MultipleInvalidRelationErrors
12
- from oarepo_runtime.services.relations.mapping import RelationsMapping
13
-
14
- from .lookup import LookupResult, lookup_key
15
-
16
-
17
- class RelationResult:
18
- def __init__(self, field, record, cache) -> None:
19
- self.field = field
20
- self.record = record
21
- self.cache = cache
22
-
23
- def validate(self, raise_first_exception=True):
24
- found: List[LookupResult] = lookup_key(self.record, self.field.key)
25
- exceptions = []
26
- for relation in found:
27
- try:
28
- resolved_object = self._resolve_lookup_result(relation)
29
-
30
- if self.field.value_check:
31
- transformed_data = {}
32
- self._get_dereferenced_value(
33
- transformed_data, resolved_object, relation
34
- )
35
- self._value_check(relation.value, transformed_data)
36
- except Exception as e:
37
- if raise_first_exception:
38
- raise
39
- exceptions.append((relation, e))
40
- if exceptions:
41
- raise MultipleInvalidRelationErrors(exceptions)
42
-
43
- def _resolve_lookup_result(self, relation):
44
- if not isinstance(relation.value, dict):
45
- raise InvalidRelationValue(
46
- f"Value at path {relation.path} must be dict, found {relation.value}"
47
- )
48
- relation_id = self._lookup_id(relation)
49
- resolved_object = self.resolve(relation_id)
50
- if resolved_object is None:
51
- raise InvalidRelationValue(f"Could not resolve relation id {relation_id}.")
52
- return resolved_object
53
-
54
- def clean(self):
55
- """Clean the dereferenced attributes inside the record."""
56
- found: List[LookupResult] = lookup_key(self.record, self.field.key)
57
- for relation in found:
58
- self._clean_one(relation)
59
-
60
- def dereference(self):
61
- """Dereference the relation field object inside the record."""
62
- found: List[LookupResult] = lookup_key(self.record, self.field.key)
63
- for relation in found:
64
- self._dereference_one(relation)
65
-
66
- def _clean_one(self, relation: LookupResult):
67
- """
68
- Cleans the relation. The default implementation does nothing - the relation has been
69
- validated,
70
- """
71
-
72
- def _needs_update_relation_value(self, _relation: LookupResult):
73
- """
74
- Returns True if the relation needs resolving and updating value
75
-
76
- :param relation: relation being processed
77
- """
78
- return True
79
-
80
- def _add_version_info(self, data, relation: LookupResult, resolved_object):
81
- """
82
- Adds versioning info on relation data
83
-
84
- :param data: relation data
85
- :param relation: relation being processed
86
- :param resolved_object: the object to which this relation points to
87
- """
88
-
89
- def _dereference_one(self, relation: LookupResult):
90
- """Dereference a single object into a dict."""
91
- if not self._needs_update_relation_value(relation):
92
- return
93
-
94
- data = relation.value
95
- obj = self._resolve_lookup_result(relation)
96
- self._get_dereferenced_value(data, obj, relation)
97
-
98
- return data
99
-
100
- def _get_dereferenced_value(self, data, obj, relation):
101
- # Inject selected key/values from related record into
102
- # the current record.
103
-
104
- # From record dictionary
105
- if self.field.keys is None:
106
- data.update({k: v for k, v in obj.items()})
107
- else:
108
- new_obj = {}
109
- for k in self.field.keys:
110
- try:
111
- key = self._get_dereference_key(k, relation)
112
- target = self._get_dereference_target(k, relation)
113
- val = dict_lookup(obj, key)
114
- if val:
115
- dict_set(new_obj, target, val)
116
- except KeyError:
117
- pass
118
- data.update(new_obj)
119
-
120
- # From record attributes (i.e. system fields)
121
- for a in self.field.attrs:
122
- data[a] = getattr(obj, a)
123
-
124
- self._add_version_info(data, relation, obj)
125
-
126
- def _get_dereference_key(self, key, _relation: LookupResult):
127
- if isinstance(key, dict):
128
- return key["key"]
129
- return key
130
-
131
- def _get_dereference_target(self, key, _relation: LookupResult):
132
- if isinstance(key, dict):
133
- return key["target"]
134
- return key
135
-
136
- def _value_check(self, value_to_check, object):
137
- """Checks if the value is present in the object."""
138
- # TODO: this is way too complicated, should refactor it (and look at the code coverage as well)
139
- for key, value in value_to_check.items():
140
- if key not in object:
141
- raise InvalidCheckValue(f"Invalid key {key}.")
142
- if isinstance(value, dict):
143
- self._value_check(value, object[key])
144
- else:
145
- if not isinstance(value, list):
146
- raise InvalidCheckValue(
147
- f"Invalid value_check value: {value}; it must be " "a list"
148
- )
149
- elif isinstance(object[key], list):
150
- value_exist = set(object[key]).intersection(set(value))
151
- if not value_exist:
152
- raise InvalidCheckValue(
153
- f"Failed cross checking value_check value "
154
- f"{value} with record value {object[key]}."
155
- )
156
- else:
157
- if object[key] not in value:
158
- raise InvalidCheckValue(
159
- f"Failed cross checking value_check value "
160
- f"{value} with record value {object[key]}."
161
- )
162
-
163
- def _lookup_id(self, relation: LookupResult):
164
- relation_id = relation.value.get("id", None)
165
- if not relation_id:
166
- raise InvalidRelationValue(
167
- f"Value at path {relation.path} must contain non-empty 'id' field, found {relation.value}"
168
- )
169
- return relation_id
170
-
171
- def _store_id(self, relation: LookupResult, relation_id):
172
- relation.value["id"] = relation_id
173
-
174
- def resolve(self, id_):
175
- raise NotImplementedError("Please implement this method in your subclass")
176
-
177
-
178
- class UnstrictRelationResult(RelationResult):
179
-
180
- def _resolve_lookup_result(self, relation):
181
- if not isinstance(relation.value, dict):
182
- raise InvalidRelationValue(
183
- f"Value at path {relation.path} must be dict, found {relation.value}"
184
- )
185
- if "id" not in relation.value:
186
- return relation.value
187
- relation_id = self._lookup_id(relation)
188
- resolved_object = self.resolve(relation_id, relation.value)
189
- if resolved_object is None:
190
- raise InvalidRelationValue(f"Could not resolve relation id {relation_id}.")
191
- return resolved_object
192
-
193
- def _dereference_one(self, relation: LookupResult):
194
- """Dereference a single object into a dict."""
195
- if not self._needs_update_relation_value(relation):
196
- return
197
-
198
- data = relation.value
199
- obj = self._resolve_lookup_result(relation)
200
- if type(obj) is not dict:
201
- self._get_dereferenced_value(data, obj, relation)
202
-
203
- return data
204
-
205
-
206
- class Relation:
207
- result_cls = RelationResult
208
-
209
- def __init__(
210
- self,
211
- key=None,
212
- attrs=None,
213
- keys=None,
214
- _clear_empty=True,
215
- value_check=None,
216
- ):
217
- """Initialize the relation."""
218
- self.key = key
219
- self.attrs = attrs or []
220
- self.keys = keys or []
221
- self._clear_empty = _clear_empty
222
- self.value_check = value_check
223
-
224
- def get_value(self, record, cache):
225
- """Return the resolved relation from a record."""
226
- return self.result_cls(self, record, cache)
227
-
228
-
229
- class RelationsField(SystemField):
230
- # taken from RelationsField
231
- def __init__(self, **fields):
232
- """Initialize the field."""
233
- super().__init__()
234
- assert all(isinstance(f, Relation) for f in fields.values())
235
- self._original_fields = fields
236
-
237
- def __getattr__(self, name):
238
- """Get a field definition."""
239
- if name in self._fields:
240
- return self._fields[name]
241
- raise AttributeError
242
-
243
- def __iter__(self):
244
- """Iterate over the configured fields."""
245
- return iter(getattr(self, f) for f in self._fields)
246
-
247
- def __contains__(self, name):
248
- """Return if a field exists in the configured fields."""
249
- return name in self._fields
250
-
251
- #
252
- # Properties
253
- #
254
- @cached_property
255
- def _fields(self):
256
- """Get the fields."""
257
- return self._original_fields
258
-
259
- #
260
- # Helpers
261
- #
262
- def obj(self, instance):
263
- """Get the relations object."""
264
- # Check cache
265
- obj = self._get_cache(instance)
266
- if obj:
267
- return obj
268
- obj = RelationsMapping(record=instance, fields=self._fields)
269
- self._set_cache(instance, obj)
270
- return obj
271
-
272
- #
273
- # Data descriptor
274
- #
275
- def __get__(self, record, owner=None):
276
- """Accessing the attribute."""
277
- # Class access
278
- if record is None:
279
- return self
280
- return self.obj(record)
281
-
282
- def __set__(self, instance, values):
283
- """Setting the attribute."""
284
- obj = self.obj(instance)
285
- for k, v in values.items():
286
- setattr(obj, k, v)
287
-
288
- #
289
- # Record extension
290
- #
291
- def pre_commit(self, record):
292
- """Initialise the model field."""
293
- obj = self.obj(record)
294
- obj.validate()
295
- obj.clean()
296
- obj.dereference()
@@ -1,46 +0,0 @@
1
- from invenio_records.systemfields.relations import InvalidRelationValue
2
-
3
- from .base import Relation, RelationResult
4
- from .lookup import LookupResult, lookup_key
5
-
6
-
7
- class InternalResult(RelationResult):
8
- def resolve(self, id_):
9
- related_part = self.field.related_part
10
-
11
- if not related_part:
12
- return self.record
13
-
14
- potential_values = list(lookup_key(self.record, related_part))
15
-
16
- if not id_:
17
- if len(potential_values) > 1:
18
- raise InvalidRelationValue(
19
- "Relation returned more than one part at "
20
- f"{related_part} but has no id to check those parts against"
21
- )
22
- return potential_values[0].value
23
-
24
- for rel in potential_values:
25
- if not isinstance(rel.value, dict):
26
- raise KeyError(
27
- f"Related part {related_part} does not point to an array of objects at path "
28
- f"{rel.path}- array member is {type(rel.value)}: {rel.value}"
29
- )
30
-
31
- if id_ == rel.value.get("id", None):
32
- return rel.value
33
-
34
- raise KeyError(f"No data for relation at path {related_part} with id {id_}")
35
-
36
- def _lookup_id(self, relation: LookupResult):
37
- relation_id = relation.value.get("id", None)
38
- return relation_id
39
-
40
-
41
- class InternalRelation(Relation):
42
- result_cls = InternalResult
43
-
44
- def __init__(self, key=None, related_part=None, **kwargs):
45
- super().__init__(key=key, **kwargs)
46
- self.related_part = related_part
@@ -1,28 +0,0 @@
1
- import dataclasses
2
- from typing import Any, Tuple
3
-
4
-
5
- @dataclasses.dataclass
6
- class LookupResult:
7
- path: Tuple[str]
8
- value: Any
9
-
10
-
11
- def lookup_key(record, key):
12
- """more generic version of dict_lookup, for arrays does not look up by index but returns all members of array"""
13
-
14
- def _internal_lookup_key(key, data, path: Tuple):
15
- if isinstance(data, (tuple, list)):
16
- for idx, d in enumerate(data):
17
- yield from _internal_lookup_key(key, d, path + (idx,))
18
- return
19
- if not key:
20
- yield LookupResult(path, data)
21
- return
22
- if not isinstance(data, dict):
23
- return
24
- if key[0] in data:
25
- yield from _internal_lookup_key(key[1:], data[key[0]], path + (key[0],))
26
-
27
- key = key.split(".")
28
- return list(_internal_lookup_key(key, record, tuple()))
@@ -1,102 +0,0 @@
1
- from invenio_db import db
2
-
3
- from oarepo_runtime.services.relations.errors import InvalidRelationError
4
- from sqlalchemy.exc import NoResultFound
5
-
6
- from .base import Relation, RelationResult, UnstrictRelationResult
7
- from .lookup import LookupResult
8
-
9
- class PIDRelationResult(RelationResult):
10
- def resolve(self, id_, data = None):
11
- """Resolve the value using the record class."""
12
- # TODO: handle permissions here !!!!!!
13
- try:
14
- pid_field_context = self.field.pid_field
15
- try:
16
- pid_type = getattr(pid_field_context, "pid_type", None)
17
- except:
18
- pass
19
-
20
- if pid_type is None:
21
- pid_field = pid_field_context.field
22
- if pid_field._provider:
23
- if hasattr(pid_field._provider, "pid_type"):
24
- pid_type = pid_field._provider.pid_type
25
- else:
26
- pid_type = self.field.pid_field.record_cls.__name__
27
- else:
28
- if hasattr(pid_field, "_pid_type"):
29
- pid_type = pid_field._pid_type
30
- else:
31
- pid_type = self.field.pid_field.record_cls.__name__
32
- except Exception as e:
33
- raise InvalidRelationError(
34
- f"PID type for field {self.field.key} has not been found or there was an exception accessing it.",
35
- related_id=id_,
36
- location=self.field.key,
37
- ) from e
38
-
39
- cache_key = (pid_type, id_)
40
- if cache_key in self.cache:
41
- obj = self.cache[cache_key]
42
- return obj
43
-
44
- try:
45
- obj = pid_field_context.resolve(id_)
46
- if hasattr(obj, "relations") and obj.relations and hasattr(obj.relations, "dereference"):
47
- obj.relations.dereference()
48
- # We detach the related record model from the database session when
49
- # we add it in the cache. Otherwise, accessing the cached record
50
- # model, will execute a new select query after a db.session.commit.
51
- db.session.expunge(obj.model)
52
- self.cache[cache_key] = obj
53
- return obj
54
- except Exception as e:
55
- raise InvalidRelationError(
56
- f"Repository object {cache_key} has not been found or there was an exception accessing it. "
57
- f"Referenced from {self.field.key}.",
58
- related_id=id_,
59
- location=self.field.key,
60
- ) from e
61
-
62
- def _needs_update_relation_value(self, relation: LookupResult):
63
- # Don't dereference if already referenced.
64
- return "@v" not in relation.value
65
-
66
- def _add_version_info(self, data, relation: LookupResult, resolved_object):
67
- data["@v"] = f"{resolved_object.id}::{resolved_object.revision_id}"
68
-
69
- class UnstrictPIDRelationResult(PIDRelationResult, UnstrictRelationResult):
70
-
71
- def resolve(self, id_, data):
72
- try:
73
- return super().resolve(id_, data)
74
- except InvalidRelationError as e:
75
- if isinstance(e.__cause__, NoResultFound):
76
- return data
77
- raise
78
-
79
- class PIDRelation(Relation):
80
- result_cls = PIDRelationResult
81
-
82
- def __init__(self, key=None, pid_field=None, **kwargs):
83
- super().__init__(key=key, **kwargs)
84
- self.pid_field = pid_field
85
-
86
- class UnstrictPIDRelation(Relation):
87
- result_cls = UnstrictPIDRelationResult
88
-
89
- def __init__(self, key=None, pid_field=None, **kwargs):
90
- super().__init__(key=key, **kwargs)
91
- self.pid_field = pid_field
92
-
93
- class MetadataRelationResult(PIDRelationResult):
94
- def _dereference_one(self, relation: LookupResult):
95
- ret = super()._dereference_one(relation)
96
- if "metadata" in ret:
97
- ret.update(ret.pop("metadata"))
98
- return ret
99
-
100
-
101
- class MetadataPIDRelation(PIDRelation):
102
- result_cls = MetadataRelationResult
@@ -1,45 +0,0 @@
1
- from invenio_access.permissions import system_identity
2
- from invenio_records.systemfields import SystemField
3
- from invenio_records_resources.proxies import current_service_registry
4
-
5
- from oarepo_runtime.datastreams.utils import get_file_service_for_record_service
6
- from oarepo_runtime.records.systemfields.mapping import MappingSystemFieldMixin
7
-
8
-
9
- class FeaturedFileFieldResult:
10
- def __init__(self, record=None):
11
- super().__init__()
12
- self.record = record
13
-
14
-
15
- class FeaturedFileField(MappingSystemFieldMixin, SystemField):
16
- def __init__(self, source_field):
17
- super(FeaturedFileField, self).__init__(source_field)
18
-
19
- def __get__(self, instance, owner):
20
- if instance is None:
21
- return self
22
- result = FeaturedFileFieldResult(record=instance)
23
- return result
24
-
25
- def search_dump(self, data, record):
26
- for service in current_service_registry._services:
27
- if getattr(
28
- current_service_registry._services[service], "record_cls"
29
- ) == type(record):
30
- file_service = get_file_service_for_record_service(
31
- record_service=current_service_registry._services[service],
32
- record=record,
33
- )
34
-
35
- files = file_service.list_files(system_identity, record["id"])
36
- file_list = list(files.entries)
37
-
38
- for file in file_list:
39
- if (
40
- file["metadata"]
41
- and "featured" in file["metadata"]
42
- and file["metadata"]["featured"]
43
- ):
44
- record["metadata"].update({"featured": file})
45
- record.commit()
@@ -1,47 +0,0 @@
1
- from inspect import isfunction
2
-
3
- from invenio_records.dictutils import dict_set
4
- from invenio_records.systemfields import SystemField
5
- from sqlalchemy.orm.exc import NoResultFound
6
-
7
- from oarepo_runtime.services.custom_fields import CustomFieldsMixin
8
-
9
-
10
- # taken from https://github.com/inveniosoftware/invenio-rdm-records/blob/master/invenio_rdm_records/records/systemfields/has_draftcheck.py
11
- class HasDraftCheckField(CustomFieldsMixin, SystemField):
12
- """PID status field which checks against an expected status."""
13
-
14
- def __init__(self, draft_cls=None, key=None, **kwargs):
15
- """Initialize the PIDField.
16
-
17
- It stores the `record.has_draft` value in the secondary storage
18
- system's record or defaults to `False` if the `draft_cls` is not passed
19
- e.g Draft records.
20
-
21
- :param key: Attribute name of the HasDraftCheckField.
22
- :param draft_cls: The draft class to use for querying.
23
- """
24
- super().__init__(key=key, **kwargs)
25
- self.draft_cls = draft_cls
26
-
27
- #
28
- # Data descriptor methods (i.e. attribute access)
29
- #
30
- def __get__(self, record, owner=None):
31
- if record is None:
32
- return self # returns the field itself.
33
-
34
- # If not draft_cls is passed return False
35
- if self.draft_cls is None:
36
- return False
37
-
38
- try:
39
- if isfunction(self.draft_cls):
40
- self.draft_cls = self.draft_cls()
41
- self.draft_cls.get_record(record.id)
42
- return True
43
- except NoResultFound:
44
- return False
45
-
46
- def pre_dump(self, record, data, **kwargs):
47
- dict_set(data, self.key, record.has_draft)