oarepo-runtime 1.10.3__py3-none-any.whl → 2.0.0.dev3__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/__init__.py +24 -0
- oarepo_runtime/api.py +111 -0
- oarepo_runtime/cli/__init__.py +10 -21
- oarepo_runtime/cli/search.py +34 -0
- oarepo_runtime/config.py +86 -13
- oarepo_runtime/ext.py +64 -82
- oarepo_runtime/proxies.py +21 -5
- oarepo_runtime/records/__init__.py +11 -50
- oarepo_runtime/records/drafts.py +24 -18
- oarepo_runtime/records/mapping.py +84 -0
- oarepo_runtime/records/pid_providers.py +43 -7
- oarepo_runtime/records/systemfields/__init__.py +15 -33
- oarepo_runtime/records/systemfields/mapping.py +41 -24
- oarepo_runtime/records/systemfields/publication_status.py +59 -0
- oarepo_runtime/services/__init__.py +12 -0
- oarepo_runtime/services/config/__init__.py +15 -21
- oarepo_runtime/services/config/link_conditions.py +69 -75
- oarepo_runtime/services/config/permissions.py +62 -0
- oarepo_runtime/services/records/__init__.py +14 -1
- oarepo_runtime/services/records/links.py +21 -11
- oarepo_runtime/services/records/mapping.py +42 -0
- oarepo_runtime/services/results.py +98 -109
- oarepo_runtime/services/schema/__init__.py +12 -44
- oarepo_runtime/services/schema/i18n.py +47 -22
- oarepo_runtime/services/schema/i18n_ui.py +61 -24
- {oarepo_runtime-1.10.3.dist-info → oarepo_runtime-2.0.0.dev3.dist-info}/METADATA +9 -21
- oarepo_runtime-2.0.0.dev3.dist-info/RECORD +30 -0
- {oarepo_runtime-1.10.3.dist-info → oarepo_runtime-2.0.0.dev3.dist-info}/WHEEL +1 -2
- oarepo_runtime-2.0.0.dev3.dist-info/entry_points.txt +5 -0
- oarepo_runtime/cli/assets.py +0 -145
- oarepo_runtime/cli/base.py +0 -25
- oarepo_runtime/cli/cf.py +0 -15
- oarepo_runtime/cli/check.py +0 -167
- oarepo_runtime/cli/configuration.py +0 -51
- oarepo_runtime/cli/fixtures.py +0 -167
- oarepo_runtime/cli/index.py +0 -272
- oarepo_runtime/cli/permissions/__init__.py +0 -6
- oarepo_runtime/cli/permissions/base.py +0 -26
- oarepo_runtime/cli/permissions/evaluate.py +0 -63
- oarepo_runtime/cli/permissions/list.py +0 -239
- oarepo_runtime/cli/permissions/search.py +0 -121
- oarepo_runtime/cli/validate.py +0 -150
- oarepo_runtime/datastreams/__init__.py +0 -38
- oarepo_runtime/datastreams/asynchronous.py +0 -247
- oarepo_runtime/datastreams/catalogue.py +0 -150
- oarepo_runtime/datastreams/datastreams.py +0 -152
- oarepo_runtime/datastreams/errors.py +0 -54
- oarepo_runtime/datastreams/ext.py +0 -41
- oarepo_runtime/datastreams/fixtures.py +0 -265
- oarepo_runtime/datastreams/json.py +0 -4
- oarepo_runtime/datastreams/readers/__init__.py +0 -39
- oarepo_runtime/datastreams/readers/attachments.py +0 -51
- oarepo_runtime/datastreams/readers/excel.py +0 -123
- oarepo_runtime/datastreams/readers/json.py +0 -27
- oarepo_runtime/datastreams/readers/service.py +0 -54
- oarepo_runtime/datastreams/readers/yaml.py +0 -14
- oarepo_runtime/datastreams/semi_asynchronous.py +0 -91
- oarepo_runtime/datastreams/synchronous.py +0 -70
- oarepo_runtime/datastreams/transformers.py +0 -18
- oarepo_runtime/datastreams/types.py +0 -323
- oarepo_runtime/datastreams/utils.py +0 -131
- oarepo_runtime/datastreams/writers/__init__.py +0 -21
- oarepo_runtime/datastreams/writers/attachments_file.py +0 -92
- oarepo_runtime/datastreams/writers/attachments_service.py +0 -118
- oarepo_runtime/datastreams/writers/publish.py +0 -70
- oarepo_runtime/datastreams/writers/service.py +0 -175
- oarepo_runtime/datastreams/writers/utils.py +0 -30
- oarepo_runtime/datastreams/writers/validation_errors.py +0 -20
- oarepo_runtime/datastreams/writers/yaml.py +0 -56
- oarepo_runtime/ext_config.py +0 -67
- oarepo_runtime/i18n/__init__.py +0 -3
- oarepo_runtime/info/__init__.py +0 -0
- oarepo_runtime/info/check.py +0 -95
- oarepo_runtime/info/permissions/__init__.py +0 -0
- oarepo_runtime/info/permissions/debug.py +0 -191
- oarepo_runtime/info/views.py +0 -586
- oarepo_runtime/profile.py +0 -60
- oarepo_runtime/records/dumpers/__init__.py +0 -8
- oarepo_runtime/records/dumpers/edtf_interval.py +0 -38
- oarepo_runtime/records/dumpers/multilingual_dumper.py +0 -34
- oarepo_runtime/records/entity_resolvers/__init__.py +0 -13
- oarepo_runtime/records/entity_resolvers/proxies.py +0 -57
- oarepo_runtime/records/mappings/__init__.py +0 -0
- oarepo_runtime/records/mappings/rdm_parent_mapping.json +0 -483
- oarepo_runtime/records/owners/__init__.py +0 -3
- oarepo_runtime/records/owners/registry.py +0 -22
- oarepo_runtime/records/relations/__init__.py +0 -22
- oarepo_runtime/records/relations/base.py +0 -296
- oarepo_runtime/records/relations/internal.py +0 -46
- oarepo_runtime/records/relations/lookup.py +0 -28
- oarepo_runtime/records/relations/pid_relation.py +0 -102
- oarepo_runtime/records/systemfields/featured_file.py +0 -45
- oarepo_runtime/records/systemfields/has_draftcheck.py +0 -47
- oarepo_runtime/records/systemfields/icu.py +0 -371
- oarepo_runtime/records/systemfields/owner.py +0 -115
- oarepo_runtime/records/systemfields/record_status.py +0 -35
- oarepo_runtime/records/systemfields/selectors.py +0 -98
- oarepo_runtime/records/systemfields/synthetic.py +0 -130
- oarepo_runtime/resources/__init__.py +0 -4
- oarepo_runtime/resources/config.py +0 -12
- oarepo_runtime/resources/file_resource.py +0 -15
- oarepo_runtime/resources/json_serializer.py +0 -27
- oarepo_runtime/resources/localized_ui_json_serializer.py +0 -54
- oarepo_runtime/resources/resource.py +0 -53
- oarepo_runtime/resources/responses.py +0 -20
- oarepo_runtime/services/components.py +0 -429
- oarepo_runtime/services/config/draft_link.py +0 -23
- oarepo_runtime/services/config/permissions_presets.py +0 -174
- oarepo_runtime/services/config/service.py +0 -117
- oarepo_runtime/services/custom_fields/__init__.py +0 -80
- oarepo_runtime/services/custom_fields/mappings.py +0 -188
- oarepo_runtime/services/entity/__init__.py +0 -0
- oarepo_runtime/services/entity/config.py +0 -14
- oarepo_runtime/services/entity/schema.py +0 -9
- oarepo_runtime/services/entity/service.py +0 -48
- oarepo_runtime/services/expansions/__init__.py +0 -0
- oarepo_runtime/services/expansions/expandable_fields.py +0 -21
- oarepo_runtime/services/expansions/service.py +0 -4
- oarepo_runtime/services/facets/__init__.py +0 -33
- oarepo_runtime/services/facets/base.py +0 -12
- oarepo_runtime/services/facets/date.py +0 -72
- oarepo_runtime/services/facets/enum.py +0 -11
- oarepo_runtime/services/facets/facet_groups_names.py +0 -17
- oarepo_runtime/services/facets/max_facet.py +0 -13
- oarepo_runtime/services/facets/multilingual_facet.py +0 -33
- oarepo_runtime/services/facets/nested_facet.py +0 -32
- oarepo_runtime/services/facets/params.py +0 -192
- oarepo_runtime/services/facets/year_histogram.py +0 -200
- oarepo_runtime/services/files/__init__.py +0 -8
- oarepo_runtime/services/files/components.py +0 -62
- oarepo_runtime/services/files/service.py +0 -16
- oarepo_runtime/services/generators.py +0 -10
- oarepo_runtime/services/permissions/__init__.py +0 -3
- oarepo_runtime/services/permissions/generators.py +0 -103
- oarepo_runtime/services/relations/__init__.py +0 -0
- oarepo_runtime/services/relations/components.py +0 -15
- oarepo_runtime/services/relations/errors.py +0 -18
- oarepo_runtime/services/relations/mapping.py +0 -38
- oarepo_runtime/services/schema/cf.py +0 -13
- oarepo_runtime/services/schema/i18n_validation.py +0 -7
- oarepo_runtime/services/schema/marshmallow.py +0 -44
- oarepo_runtime/services/schema/marshmallow_to_json_schema.py +0 -72
- oarepo_runtime/services/schema/oneofschema.py +0 -192
- oarepo_runtime/services/schema/polymorphic.py +0 -21
- oarepo_runtime/services/schema/rdm.py +0 -146
- oarepo_runtime/services/schema/rdm_ui.py +0 -156
- oarepo_runtime/services/schema/ui.py +0 -251
- oarepo_runtime/services/schema/validation.py +0 -70
- oarepo_runtime/services/search.py +0 -282
- oarepo_runtime/services/service.py +0 -61
- oarepo_runtime/tasks.py +0 -6
- oarepo_runtime/translations/cs/LC_MESSAGES/messages.mo +0 -0
- oarepo_runtime/translations/cs/LC_MESSAGES/messages.po +0 -95
- oarepo_runtime/translations/default_translations.py +0 -6
- oarepo_runtime/translations/en/LC_MESSAGES/messages.mo +0 -0
- oarepo_runtime/translations/en/LC_MESSAGES/messages.po +0 -97
- oarepo_runtime/translations/messages.pot +0 -100
- oarepo_runtime/uow.py +0 -146
- oarepo_runtime/utils/__init__.py +0 -0
- oarepo_runtime/utils/functools.py +0 -37
- oarepo_runtime/utils/identity_utils.py +0 -35
- oarepo_runtime/utils/index.py +0 -11
- oarepo_runtime/utils/path.py +0 -97
- oarepo_runtime-1.10.3.dist-info/RECORD +0 -163
- oarepo_runtime-1.10.3.dist-info/entry_points.txt +0 -16
- oarepo_runtime-1.10.3.dist-info/top_level.txt +0 -2
- tests/marshmallow_to_json/__init__.py +0 -0
- tests/marshmallow_to_json/test_datacite_ui_schema.py +0 -1410
- tests/marshmallow_to_json/test_simple_schema.py +0 -52
- tests/pkg_data/__init__.py +0 -0
- {oarepo_runtime-1.10.3.dist-info → oarepo_runtime-2.0.0.dev3.dist-info}/licenses/LICENSE +0 -0
@@ -1,429 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
|
3
|
-
import inspect
|
4
|
-
from collections import defaultdict
|
5
|
-
from dataclasses import dataclass, field
|
6
|
-
from typing import Any, Type
|
7
|
-
|
8
|
-
from flask import current_app
|
9
|
-
from invenio_accounts.models import User
|
10
|
-
from invenio_base.utils import obj_or_import_string
|
11
|
-
from invenio_drafts_resources.services.records.config import (
|
12
|
-
RecordServiceConfig as DraftsRecordServiceConfig,
|
13
|
-
)
|
14
|
-
from invenio_rdm_records.services.config import RDMRecordServiceConfig
|
15
|
-
from invenio_records import Record
|
16
|
-
from invenio_records_resources.services import FileServiceConfig
|
17
|
-
from invenio_records_resources.services.records.config import (
|
18
|
-
RecordServiceConfig as RecordsRecordServiceConfig,
|
19
|
-
)
|
20
|
-
|
21
|
-
from oarepo_runtime.proxies import current_oarepo
|
22
|
-
from oarepo_runtime.services.custom_fields import (
|
23
|
-
CustomFields,
|
24
|
-
CustomFieldsMixin,
|
25
|
-
InlinedCustomFields,
|
26
|
-
)
|
27
|
-
from oarepo_runtime.services.generators import RecordOwners
|
28
|
-
|
29
|
-
try:
|
30
|
-
from invenio_drafts_resources.services.records.uow import ParentRecordCommitOp
|
31
|
-
except ImportError:
|
32
|
-
from invenio_records_resources.services.uow import (
|
33
|
-
RecordCommitOp as ParentRecordCommitOp,
|
34
|
-
)
|
35
|
-
|
36
|
-
from invenio_records_resources.services.records.components import ServiceComponent
|
37
|
-
|
38
|
-
|
39
|
-
class OwnersComponent(ServiceComponent):
|
40
|
-
def create(self, identity, *, record, **kwargs):
|
41
|
-
"""Create handler."""
|
42
|
-
self.add_owner(identity, record)
|
43
|
-
|
44
|
-
def add_owner(self, identity, record, commit=False):
|
45
|
-
if not hasattr(identity, "id") or not isinstance(identity.id, int):
|
46
|
-
return
|
47
|
-
|
48
|
-
owners = getattr(record.parent, "owners", None)
|
49
|
-
if owners is not None:
|
50
|
-
user = User.query.filter_by(id=identity.id).first()
|
51
|
-
record.parent.owners.add(user)
|
52
|
-
if commit:
|
53
|
-
self.uow.register(ParentRecordCommitOp(record.parent))
|
54
|
-
|
55
|
-
def update(self, identity, *, record, **kwargs):
|
56
|
-
"""Update handler."""
|
57
|
-
self.add_owner(identity, record, commit=True)
|
58
|
-
|
59
|
-
def update_draft(self, identity, *, record, **kwargs):
|
60
|
-
"""Update handler."""
|
61
|
-
self.add_owner(identity, record, commit=True)
|
62
|
-
|
63
|
-
def search_drafts(self, identity, search, params, **kwargs):
|
64
|
-
new_term = RecordOwners().query_filter(identity)
|
65
|
-
if new_term:
|
66
|
-
return search.filter(new_term)
|
67
|
-
return search
|
68
|
-
|
69
|
-
|
70
|
-
from datetime import datetime
|
71
|
-
|
72
|
-
|
73
|
-
class DateIssuedComponent(ServiceComponent):
|
74
|
-
def publish(self, identity, data=None, record=None, errors=None, **kwargs):
|
75
|
-
"""Create a new record."""
|
76
|
-
if "dateIssued" not in record["metadata"]:
|
77
|
-
record["metadata"]["dateIssued"] = datetime.today().strftime("%Y-%m-%d")
|
78
|
-
|
79
|
-
|
80
|
-
class CFRegistry:
|
81
|
-
def __init__(self):
|
82
|
-
self.custom_field_names = defaultdict(list)
|
83
|
-
|
84
|
-
def lookup(self, record_type: Type[Record]):
|
85
|
-
if record_type not in self.custom_field_names:
|
86
|
-
for fld in inspect.getmembers(
|
87
|
-
record_type, lambda x: isinstance(x, CustomFieldsMixin)
|
88
|
-
):
|
89
|
-
self.custom_field_names[record_type].append(fld[1])
|
90
|
-
return self.custom_field_names[record_type]
|
91
|
-
|
92
|
-
|
93
|
-
cf_registry = CFRegistry()
|
94
|
-
|
95
|
-
|
96
|
-
class CustomFieldsComponent(ServiceComponent):
|
97
|
-
def create(self, identity, data=None, record=None, **kwargs):
|
98
|
-
"""Create a new record."""
|
99
|
-
self._set_cf_to_record(record, data)
|
100
|
-
|
101
|
-
def update(self, identity, data=None, record=None, **kwargs):
|
102
|
-
"""Update a record."""
|
103
|
-
self._set_cf_to_record(record, data)
|
104
|
-
|
105
|
-
def _set_cf_to_record(self, record, data):
|
106
|
-
for cf in cf_registry.lookup(type(record)):
|
107
|
-
if isinstance(cf, CustomFields):
|
108
|
-
setattr(record, cf.attr_name, data.get(cf.key, {}))
|
109
|
-
elif isinstance(cf, InlinedCustomFields):
|
110
|
-
config = current_app.config.get(cf.config_key, {})
|
111
|
-
for c in config:
|
112
|
-
record[c.name] = data.get(c.name)
|
113
|
-
|
114
|
-
|
115
|
-
def process_service_configs(service_config, *additional_components):
|
116
|
-
processed_components = []
|
117
|
-
target_classes = {
|
118
|
-
RDMRecordServiceConfig,
|
119
|
-
DraftsRecordServiceConfig,
|
120
|
-
RecordsRecordServiceConfig,
|
121
|
-
FileServiceConfig,
|
122
|
-
}
|
123
|
-
|
124
|
-
for end_index, cls in enumerate(type(service_config).mro()):
|
125
|
-
if cls in target_classes:
|
126
|
-
break
|
127
|
-
|
128
|
-
# We need this because if the "build" function is present in service_config,
|
129
|
-
# there are two service_config instances in the MRO (Method Resolution Order) output.
|
130
|
-
start_index = 2 if hasattr(service_config, "build") else 1
|
131
|
-
|
132
|
-
service_configs = type(service_config).mro()[start_index : end_index + 1]
|
133
|
-
for config in service_configs:
|
134
|
-
if hasattr(config, "build"):
|
135
|
-
config = config.build(current_app)
|
136
|
-
|
137
|
-
if hasattr(config, "components"):
|
138
|
-
component_property = config.components
|
139
|
-
if isinstance(component_property, list):
|
140
|
-
processed_components.extend(component_property)
|
141
|
-
elif isinstance(component_property, tuple):
|
142
|
-
processed_components.extend(list(component_property))
|
143
|
-
else:
|
144
|
-
raise ValueError(f"{config} component's definition is not supported")
|
145
|
-
|
146
|
-
processed_components.extend(additional_components)
|
147
|
-
|
148
|
-
for excluded_component in current_oarepo.rdm_excluded_components:
|
149
|
-
if excluded_component in processed_components:
|
150
|
-
processed_components.remove(excluded_component)
|
151
|
-
|
152
|
-
processed_components = _sort_components(processed_components)
|
153
|
-
return processed_components
|
154
|
-
|
155
|
-
|
156
|
-
@dataclass
|
157
|
-
class ComponentPlacement:
|
158
|
-
"""Component placement in the list of components.
|
159
|
-
|
160
|
-
This is a helper class used in the component ordering algorithm.
|
161
|
-
"""
|
162
|
-
|
163
|
-
component: Type[ServiceComponent]
|
164
|
-
"""Component to be ordered."""
|
165
|
-
|
166
|
-
depends_on: list[ComponentPlacement] = field(default_factory=list)
|
167
|
-
"""List of components this one depends on.
|
168
|
-
|
169
|
-
The components must be classes of ServiceComponent.
|
170
|
-
"""
|
171
|
-
|
172
|
-
affects: list[ComponentPlacement] = field(default_factory=list)
|
173
|
-
"""List of components that depend on this one."""
|
174
|
-
|
175
|
-
star_depends: bool = False
|
176
|
-
"""True if this component depends on all other components."""
|
177
|
-
|
178
|
-
star_affects: bool = False
|
179
|
-
"""True if this component affects all other components."""
|
180
|
-
|
181
|
-
def __hash__(self) -> int:
|
182
|
-
return id(self.component)
|
183
|
-
|
184
|
-
def __eq__(self, other: Any) -> bool:
|
185
|
-
return self.component is other.component
|
186
|
-
|
187
|
-
def __repr__(self) -> str:
|
188
|
-
depends_on = [d.component.__name__ for d in self.depends_on]
|
189
|
-
affects = [a.component.__name__ for a in self.affects]
|
190
|
-
if self.star_affects:
|
191
|
-
affects.append("*")
|
192
|
-
if self.star_depends:
|
193
|
-
depends_on.append("*")
|
194
|
-
r = [f"<{self.component.__name__}"]
|
195
|
-
if depends_on:
|
196
|
-
r.append(f" depends_on: {depends_on}")
|
197
|
-
if affects:
|
198
|
-
r.append(f" affects: {affects}")
|
199
|
-
r.append(">")
|
200
|
-
return "".join(r)
|
201
|
-
|
202
|
-
def __str__(self) -> str:
|
203
|
-
return repr(self)
|
204
|
-
|
205
|
-
|
206
|
-
def _sort_components(components) -> list[Type[ServiceComponent]]:
|
207
|
-
"""Sort components based on their dependencies while trying to
|
208
|
-
keep the initial order as far as possible.
|
209
|
-
|
210
|
-
Sorting algorithm:
|
211
|
-
|
212
|
-
1. Select all "affects" components that has "*" in their "affects" list.
|
213
|
-
2. Merge these components preserving other other "affects" and "depends_on" settings
|
214
|
-
and output these
|
215
|
-
|
216
|
-
3. put "depends_on: *" components aside for the moment
|
217
|
-
4. Sort the remaining components by their dependencies
|
218
|
-
|
219
|
-
5. process depends_on: * in a similar way as in 2.
|
220
|
-
"""
|
221
|
-
|
222
|
-
placements: list[ComponentPlacement] = _prepare_component_placement(components)
|
223
|
-
|
224
|
-
# placements that must be first as they affect all other components
|
225
|
-
affects_placements = [p for p in placements if p.star_affects]
|
226
|
-
|
227
|
-
# placements that must be last as they depend on all other components
|
228
|
-
depends_on_placements = [p for p in placements if p.star_depends]
|
229
|
-
|
230
|
-
# if a component affects another that affects all components,
|
231
|
-
# add it to affects_placements
|
232
|
-
#
|
233
|
-
# A[affects *] B[affects A] C => adds B to affects_placements
|
234
|
-
modified = True
|
235
|
-
while modified:
|
236
|
-
modified = False
|
237
|
-
for p in placements:
|
238
|
-
if (
|
239
|
-
any(q in affects_placements for q in p.affects)
|
240
|
-
and p not in affects_placements
|
241
|
-
):
|
242
|
-
affects_placements.append(p)
|
243
|
-
modified = True
|
244
|
-
|
245
|
-
# if a component depends on another that depends on all components,
|
246
|
-
# add it to depends_on_placements
|
247
|
-
# A[depends_on *] B[depends_on A] C => adds B to depends_on_placements
|
248
|
-
modified = True
|
249
|
-
while modified:
|
250
|
-
modified = False
|
251
|
-
for p in placements:
|
252
|
-
if (
|
253
|
-
any(q in depends_on_placements for q in p.depends_on)
|
254
|
-
and p not in depends_on_placements
|
255
|
-
):
|
256
|
-
depends_on_placements.append(p)
|
257
|
-
modified = True
|
258
|
-
|
259
|
-
# those that do not affect or depend on all components
|
260
|
-
middle_placements = [
|
261
|
-
p
|
262
|
-
for p in placements
|
263
|
-
if p not in depends_on_placements and p not in affects_placements
|
264
|
-
]
|
265
|
-
|
266
|
-
# sort placements inside each group by their respective depends on and affects
|
267
|
-
# relationships, ignoring the star relationships
|
268
|
-
ret = []
|
269
|
-
ret.extend(_sort_placements(affects_placements))
|
270
|
-
ret.extend(_sort_placements(middle_placements))
|
271
|
-
ret.extend(_sort_placements(depends_on_placements))
|
272
|
-
return ret
|
273
|
-
|
274
|
-
|
275
|
-
def _sort_placements(placements):
|
276
|
-
"""Sort placements based on their dependencies.
|
277
|
-
|
278
|
-
The algorithm tries to keep the initial order as far as possible,
|
279
|
-
while still respecting the dependencies.
|
280
|
-
|
281
|
-
At first, for each component that affects another component, the algorithm
|
282
|
-
moves the affecting component before the affected one one step at a time.
|
283
|
-
|
284
|
-
When no more such moves are possible, the algorithm moves to the next step
|
285
|
-
and does similar thing for components that depend on another component.
|
286
|
-
|
287
|
-
The algorithm is repeated until all components are sorted. If they can not
|
288
|
-
be after a set number of iterations, the algorithm raises an exception.
|
289
|
-
"""
|
290
|
-
|
291
|
-
_filter_depends_on_and_affects(placements)
|
292
|
-
|
293
|
-
for _ in range(10):
|
294
|
-
for __ in range(10):
|
295
|
-
# move components that affect other components before them
|
296
|
-
modified = _move_affecting_components(placements)
|
297
|
-
|
298
|
-
# move components that depend on other components after them
|
299
|
-
if _move_depends_on_components(placements):
|
300
|
-
modified = True
|
301
|
-
|
302
|
-
# if the order was not modified, we are done
|
303
|
-
if not modified:
|
304
|
-
return (p.component for p in placements)
|
305
|
-
else:
|
306
|
-
# could not sort the components by simple move. This means that we are
|
307
|
-
# in a situation where A C B[affects A depends on C] - we will try to
|
308
|
-
# swap A with C and try again.
|
309
|
-
_swap_out_of_order_components(placements)
|
310
|
-
|
311
|
-
raise ValueError(f"Can not order components: {placements}")
|
312
|
-
|
313
|
-
|
314
|
-
def _swap_out_of_order_components(placements):
|
315
|
-
for idx, placement in enumerate(placements):
|
316
|
-
|
317
|
-
# we are looking for a situation: A C placement[affects A depends on C]
|
318
|
-
# so if there are not depends on and affects, try the next one
|
319
|
-
if not placement.depends_on or not placement.affects:
|
320
|
-
continue
|
321
|
-
|
322
|
-
depends_on = [(p, placements.index(p)) for p in placement.depends_on]
|
323
|
-
affects = [(p, placements.index(p)) for p in placement.affects]
|
324
|
-
|
325
|
-
# if there are no indices to swap, continue
|
326
|
-
if not depends_on or not affects:
|
327
|
-
continue
|
328
|
-
|
329
|
-
# keep the indices in order
|
330
|
-
depends_on.sort(key=lambda x: x[1])
|
331
|
-
affects.sort(key=lambda x: x[1])
|
332
|
-
|
333
|
-
depends_on_indices = [d[1] for d in depends_on]
|
334
|
-
affects_indices = [a[1] for a in affects]
|
335
|
-
|
336
|
-
swapped_depends_on = [d[0] for d in depends_on]
|
337
|
-
swapped_affects = [a[0] for a in affects]
|
338
|
-
|
339
|
-
# if the index of the component the current placement depends on
|
340
|
-
# is lower that any of the components that depend on the current placement,
|
341
|
-
# we are ok as the placement can be moved to the space between them,
|
342
|
-
# so just continue
|
343
|
-
if max(depends_on_indices) < min(affects_indices):
|
344
|
-
continue
|
345
|
-
|
346
|
-
# add all to an array and sort them. This way depends on will be after
|
347
|
-
# affects, keeping the positions inside the group
|
348
|
-
indices = sorted([*affects_indices, *depends_on_indices])
|
349
|
-
|
350
|
-
for idx, dep in zip(
|
351
|
-
indices,
|
352
|
-
[*swapped_depends_on, *swapped_affects],
|
353
|
-
):
|
354
|
-
placements[idx] = dep
|
355
|
-
|
356
|
-
|
357
|
-
def _filter_depends_on_and_affects(placements):
|
358
|
-
"""Filter out dependencies on components that are not in the placements list."""
|
359
|
-
for placement in placements:
|
360
|
-
placement.depends_on = [p for p in placement.depends_on if p in placements]
|
361
|
-
placement.affects = [p for p in placement.affects if p in placements]
|
362
|
-
|
363
|
-
|
364
|
-
def _move_affecting_components(placements):
|
365
|
-
modified = False
|
366
|
-
|
367
|
-
for idx, placement in list(enumerate(placements)):
|
368
|
-
if not placement.affects:
|
369
|
-
continue
|
370
|
-
min_index = min(placements.index(a) for a in placement.affects)
|
371
|
-
if min_index < idx:
|
372
|
-
placements.remove(placement)
|
373
|
-
placements.insert(min_index, placement)
|
374
|
-
modified = True
|
375
|
-
return modified
|
376
|
-
|
377
|
-
|
378
|
-
def _move_depends_on_components(placements):
|
379
|
-
modified = False
|
380
|
-
for idx, placement in reversed(list(enumerate(placements))):
|
381
|
-
if not placement.depends_on:
|
382
|
-
continue
|
383
|
-
max_index = max(placements.index(a) for a in placement.depends_on)
|
384
|
-
if max_index > idx:
|
385
|
-
placements.remove(placement)
|
386
|
-
placements.insert(max_index, placement)
|
387
|
-
modified = True
|
388
|
-
return modified
|
389
|
-
|
390
|
-
|
391
|
-
def _matching_placements(placements, dep_class_or_factory):
|
392
|
-
for pl in placements:
|
393
|
-
pl_component = pl.component
|
394
|
-
if not inspect.isclass(pl_component):
|
395
|
-
pl_component = type(pl_component(service=object()))
|
396
|
-
if issubclass(pl_component, dep_class_or_factory):
|
397
|
-
yield pl
|
398
|
-
|
399
|
-
|
400
|
-
def _prepare_component_placement(components) -> list[ComponentPlacement]:
|
401
|
-
"""Convert components to ComponentPlacement instances and resolve dependencies."""
|
402
|
-
placements = []
|
403
|
-
for idx, c in enumerate(components):
|
404
|
-
placement = ComponentPlacement(component=c)
|
405
|
-
placements.append(placement)
|
406
|
-
|
407
|
-
# direct dependencies
|
408
|
-
for idx, placement in enumerate(placements):
|
409
|
-
placements_without_this = placements[:idx] + placements[idx + 1 :]
|
410
|
-
placement.star_depends = "*" in getattr(placement.component, "depends_on", [])
|
411
|
-
placement.star_affects = "*" in getattr(placement.component, "affects", [])
|
412
|
-
|
413
|
-
for dep in getattr(placement.component, "depends_on", []):
|
414
|
-
if dep == "*":
|
415
|
-
continue
|
416
|
-
dep = obj_or_import_string(dep)
|
417
|
-
for pl in _matching_placements(placements_without_this, dep):
|
418
|
-
if pl not in placement.depends_on:
|
419
|
-
placement.depends_on.append(pl)
|
420
|
-
|
421
|
-
for dep in getattr(placement.component, "affects", []):
|
422
|
-
if dep == "*":
|
423
|
-
continue
|
424
|
-
dep = obj_or_import_string(dep)
|
425
|
-
for pl in _matching_placements(placements_without_this, dep):
|
426
|
-
if pl not in placement.affects:
|
427
|
-
placement.affects.append(pl)
|
428
|
-
|
429
|
-
return placements
|
@@ -1,23 +0,0 @@
|
|
1
|
-
from invenio_records_resources.services import RecordLink
|
2
|
-
|
3
|
-
from oarepo_runtime.records.drafts import get_draft
|
4
|
-
|
5
|
-
|
6
|
-
class DraftLink(RecordLink):
|
7
|
-
"""Draft link."""
|
8
|
-
|
9
|
-
def __init__(self, *args, **kwargs):
|
10
|
-
"""Initialize draft link."""
|
11
|
-
super().__init__(*args, **kwargs)
|
12
|
-
|
13
|
-
@staticmethod
|
14
|
-
def vars(record, vars):
|
15
|
-
"""Variables for the URI template."""
|
16
|
-
# Some records don't have record.pid.pid_value yet (e.g. drafts)
|
17
|
-
RecordLink.vars(record, vars)
|
18
|
-
draft_record = get_draft(record)
|
19
|
-
|
20
|
-
if draft_record:
|
21
|
-
pid_value = getattr(draft_record.pid, "pid_value", None)
|
22
|
-
if pid_value:
|
23
|
-
vars.update({"id": pid_value})
|
@@ -1,174 +0,0 @@
|
|
1
|
-
from invenio_records_permissions import RecordPermissionPolicy
|
2
|
-
from invenio_records_permissions.generators import (
|
3
|
-
AnyUser,
|
4
|
-
AuthenticatedUser,
|
5
|
-
SystemProcess,
|
6
|
-
)
|
7
|
-
|
8
|
-
|
9
|
-
class OaiHarvesterPermissionPolicy(RecordPermissionPolicy):
|
10
|
-
"""record policy for oai harvester (by default same as read only)"""
|
11
|
-
|
12
|
-
can_search = [SystemProcess(), AnyUser()]
|
13
|
-
can_read = [SystemProcess(), AnyUser()]
|
14
|
-
can_create = [SystemProcess()]
|
15
|
-
can_update = [SystemProcess()]
|
16
|
-
can_delete = [SystemProcess()]
|
17
|
-
can_manage = [SystemProcess()]
|
18
|
-
|
19
|
-
can_create_files = [SystemProcess()]
|
20
|
-
can_set_content_files = [SystemProcess()]
|
21
|
-
can_get_content_files = [AnyUser(), SystemProcess()]
|
22
|
-
can_commit_files = [SystemProcess()]
|
23
|
-
can_read_files = [AnyUser(), SystemProcess()]
|
24
|
-
can_update_files = [SystemProcess()]
|
25
|
-
can_delete_files = [SystemProcess()]
|
26
|
-
can_manage_files = [SystemProcess()]
|
27
|
-
|
28
|
-
can_edit = [SystemProcess()]
|
29
|
-
can_new_version = [SystemProcess()]
|
30
|
-
can_search_drafts = [SystemProcess()]
|
31
|
-
can_read_draft = [SystemProcess()]
|
32
|
-
can_update_draft = [SystemProcess()]
|
33
|
-
can_delete_draft = [SystemProcess()]
|
34
|
-
can_publish = [SystemProcess()]
|
35
|
-
can_search_versions = [SystemProcess()]
|
36
|
-
can_draft_create_files = [SystemProcess()]
|
37
|
-
can_draft_set_content_files = [SystemProcess()]
|
38
|
-
can_draft_get_content_files = [SystemProcess()]
|
39
|
-
can_draft_commit_files = [SystemProcess()]
|
40
|
-
can_draft_read_files = [SystemProcess()]
|
41
|
-
can_draft_update_files = [SystemProcess()]
|
42
|
-
can_draft_delete_files = [SystemProcess()]
|
43
|
-
|
44
|
-
|
45
|
-
class ReadOnlyPermissionPolicy(RecordPermissionPolicy):
|
46
|
-
"""record policy for read only repository"""
|
47
|
-
|
48
|
-
can_search = [SystemProcess(), AnyUser()]
|
49
|
-
can_read = [SystemProcess(), AnyUser()]
|
50
|
-
can_create = [SystemProcess()]
|
51
|
-
can_update = [SystemProcess()]
|
52
|
-
can_delete = [SystemProcess()]
|
53
|
-
can_manage = [SystemProcess()]
|
54
|
-
|
55
|
-
can_create_files = [SystemProcess()]
|
56
|
-
can_set_content_files = [SystemProcess()]
|
57
|
-
can_get_content_files = [AnyUser(), SystemProcess()]
|
58
|
-
can_commit_files = [SystemProcess()]
|
59
|
-
can_read_files = [AnyUser(), SystemProcess()]
|
60
|
-
can_update_files = [SystemProcess()]
|
61
|
-
can_delete_files = [SystemProcess()]
|
62
|
-
can_list_files = [SystemProcess()]
|
63
|
-
can_manage_files = [SystemProcess()]
|
64
|
-
|
65
|
-
can_edit = [SystemProcess()]
|
66
|
-
can_new_version = [SystemProcess()]
|
67
|
-
can_search_drafts = [SystemProcess()]
|
68
|
-
can_read_draft = [SystemProcess()]
|
69
|
-
can_update_draft = [SystemProcess()]
|
70
|
-
can_delete_draft = [SystemProcess()]
|
71
|
-
can_publish = [SystemProcess()]
|
72
|
-
can_search_versions = [SystemProcess()]
|
73
|
-
can_draft_create_files = [SystemProcess()]
|
74
|
-
can_draft_set_content_files = [SystemProcess()]
|
75
|
-
can_draft_get_content_files = [SystemProcess()]
|
76
|
-
can_draft_commit_files = [SystemProcess()]
|
77
|
-
can_draft_read_files = [SystemProcess()]
|
78
|
-
can_draft_update_files = [SystemProcess()]
|
79
|
-
can_draft_delete_files = [SystemProcess()]
|
80
|
-
|
81
|
-
can_add_community = [SystemProcess()]
|
82
|
-
can_remove_community = [SystemProcess()]
|
83
|
-
|
84
|
-
can_read_deleted = [SystemProcess()]
|
85
|
-
can_manage_record_access = [SystemProcess()]
|
86
|
-
can_lift_embargo = [SystemProcess()]
|
87
|
-
|
88
|
-
|
89
|
-
class EveryonePermissionPolicy(RecordPermissionPolicy):
|
90
|
-
"""record policy for read only repository"""
|
91
|
-
|
92
|
-
can_search = [SystemProcess(), AnyUser()]
|
93
|
-
can_read = [SystemProcess(), AnyUser()]
|
94
|
-
can_create = [SystemProcess(), AnyUser()]
|
95
|
-
can_update = [SystemProcess(), AnyUser()]
|
96
|
-
can_delete = [SystemProcess(), AnyUser()]
|
97
|
-
can_manage = [SystemProcess(), AnyUser()]
|
98
|
-
|
99
|
-
can_create_files = [SystemProcess(), AnyUser()]
|
100
|
-
can_set_content_files = [SystemProcess(), AnyUser()]
|
101
|
-
can_get_content_files = [SystemProcess(), AnyUser()]
|
102
|
-
can_commit_files = [SystemProcess(), AnyUser()]
|
103
|
-
can_read_files = [SystemProcess(), AnyUser()]
|
104
|
-
can_update_files = [SystemProcess(), AnyUser()]
|
105
|
-
can_delete_files = [SystemProcess(), AnyUser()]
|
106
|
-
can_list_files = [SystemProcess(), AnyUser()]
|
107
|
-
can_manage_files = [SystemProcess(), AnyUser()]
|
108
|
-
|
109
|
-
can_edit = [SystemProcess(), AnyUser()]
|
110
|
-
can_new_version = [SystemProcess(), AnyUser()]
|
111
|
-
can_search_drafts = [SystemProcess(), AnyUser()]
|
112
|
-
can_read_draft = [SystemProcess(), AnyUser()]
|
113
|
-
can_search_versions = [SystemProcess(), AnyUser()]
|
114
|
-
can_update_draft = [SystemProcess(), AnyUser()]
|
115
|
-
can_delete_draft = [SystemProcess(), AnyUser()]
|
116
|
-
can_publish = [SystemProcess(), AnyUser()]
|
117
|
-
can_draft_create_files = [SystemProcess(), AnyUser()]
|
118
|
-
can_draft_set_content_files = [SystemProcess(), AnyUser()]
|
119
|
-
can_draft_get_content_files = [SystemProcess(), AnyUser()]
|
120
|
-
can_draft_commit_files = [SystemProcess(), AnyUser()]
|
121
|
-
can_draft_read_files = [SystemProcess(), AnyUser()]
|
122
|
-
can_draft_update_files = [SystemProcess(), AnyUser()]
|
123
|
-
can_draft_delete_files = [SystemProcess(), AnyUser()]
|
124
|
-
|
125
|
-
can_add_community = [SystemProcess(), AnyUser()]
|
126
|
-
can_remove_community = [SystemProcess(), AnyUser()]
|
127
|
-
|
128
|
-
can_read_deleted = [SystemProcess(), AnyUser()]
|
129
|
-
can_manage_record_access = [SystemProcess(), AnyUser()]
|
130
|
-
can_lift_embargo = [SystemProcess(), AnyUser()]
|
131
|
-
|
132
|
-
|
133
|
-
class AuthenticatedPermissionPolicy(RecordPermissionPolicy):
|
134
|
-
"""record policy for read only repository"""
|
135
|
-
|
136
|
-
can_search = [SystemProcess(), AuthenticatedUser()]
|
137
|
-
can_read = [SystemProcess(), AnyUser()]
|
138
|
-
can_read_deleted = [SystemProcess(), AnyUser()]
|
139
|
-
can_create = [SystemProcess(), AuthenticatedUser()]
|
140
|
-
can_update = [SystemProcess(), AuthenticatedUser()]
|
141
|
-
can_delete = [SystemProcess(), AuthenticatedUser()]
|
142
|
-
can_manage = [SystemProcess(), AuthenticatedUser()]
|
143
|
-
|
144
|
-
can_create_files = [SystemProcess(), AuthenticatedUser()]
|
145
|
-
can_set_content_files = [SystemProcess(), AuthenticatedUser()]
|
146
|
-
can_get_content_files = [SystemProcess(), AnyUser()]
|
147
|
-
can_commit_files = [SystemProcess(), AuthenticatedUser()]
|
148
|
-
can_read_files = [SystemProcess(), AnyUser()]
|
149
|
-
can_update_files = [SystemProcess(), AuthenticatedUser()]
|
150
|
-
can_list_files = [SystemProcess(), AuthenticatedUser()]
|
151
|
-
can_manage_files = [SystemProcess(), AuthenticatedUser()]
|
152
|
-
can_delete_files = [SystemProcess(), AuthenticatedUser()]
|
153
|
-
|
154
|
-
can_edit = [SystemProcess(), AuthenticatedUser()]
|
155
|
-
can_new_version = [SystemProcess(), AuthenticatedUser()]
|
156
|
-
can_search_drafts = [SystemProcess(), AuthenticatedUser()]
|
157
|
-
can_read_draft = [SystemProcess(), AnyUser()]
|
158
|
-
can_update_draft = [SystemProcess(), AuthenticatedUser()]
|
159
|
-
can_delete_draft = [SystemProcess(), AuthenticatedUser()]
|
160
|
-
can_publish = [SystemProcess(), AuthenticatedUser()]
|
161
|
-
can_search_versions = [SystemProcess(), AuthenticatedUser()]
|
162
|
-
can_draft_create_files = [SystemProcess(), AuthenticatedUser()]
|
163
|
-
can_draft_set_content_files = [SystemProcess(), AuthenticatedUser()]
|
164
|
-
can_draft_get_content_files = [SystemProcess(), AuthenticatedUser()]
|
165
|
-
can_draft_commit_files = [SystemProcess(), AuthenticatedUser()]
|
166
|
-
can_draft_read_files = [SystemProcess(), AuthenticatedUser()]
|
167
|
-
can_draft_update_files = [SystemProcess(), AuthenticatedUser()]
|
168
|
-
can_draft_delete_files = [SystemProcess(), AuthenticatedUser()]
|
169
|
-
|
170
|
-
can_add_community = [SystemProcess(), AuthenticatedUser()]
|
171
|
-
can_remove_community = [SystemProcess(), AuthenticatedUser()]
|
172
|
-
|
173
|
-
can_manage_record_access = [SystemProcess(), AuthenticatedUser()]
|
174
|
-
can_lift_embargo = [SystemProcess(), AuthenticatedUser()]
|