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.
- oarepo_runtime/__init__.py +24 -0
- oarepo_runtime/api.py +210 -0
- oarepo_runtime/cli/__init__.py +10 -21
- oarepo_runtime/cli/search.py +34 -0
- oarepo_runtime/config.py +98 -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 +61 -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/facets/__init__.py +12 -33
- oarepo_runtime/services/facets/params.py +45 -110
- 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.dev4.dist-info}/METADATA +10 -21
- oarepo_runtime-2.0.0.dev4.dist-info/RECORD +32 -0
- {oarepo_runtime-1.10.3.dist-info → oarepo_runtime-2.0.0.dev4.dist-info}/WHEEL +1 -2
- oarepo_runtime-2.0.0.dev4.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/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/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.dev4.dist-info}/licenses/LICENSE +0 -0
oarepo_runtime/__init__.py
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2025 CESNET z.s.p.o.
|
3
|
+
#
|
4
|
+
# This file is a part of oarepo-runtime (see http://github.com/oarepo/oarepo-runtime).
|
5
|
+
#
|
6
|
+
# oarepo-runtime is free software; you can redistribute it and/or modify it
|
7
|
+
# under the terms of the MIT License; see LICENSE file for more details.
|
8
|
+
#
|
9
|
+
|
10
|
+
"""OARepo Runtime package.
|
11
|
+
|
12
|
+
This package provides support for custom fields identification and iteration and `invenio oarepo cf init`
|
13
|
+
initialization tool for customfields.
|
14
|
+
"""
|
15
|
+
|
16
|
+
from __future__ import annotations
|
17
|
+
|
18
|
+
from .api import Model
|
19
|
+
from .ext import OARepoRuntime
|
20
|
+
from .proxies import current_runtime
|
21
|
+
|
22
|
+
__version__ = "2.0.0dev4"
|
23
|
+
|
24
|
+
__all__ = ("Model", "OARepoRuntime", "__version__", "current_runtime")
|
oarepo_runtime/api.py
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2025 CESNET z.s.p.o.
|
3
|
+
#
|
4
|
+
# This file is a part of oarepo-runtime (see http://github.com/oarepo/oarepo-runtime).
|
5
|
+
#
|
6
|
+
# oarepo-runtime is free software; you can redistribute it and/or modify it
|
7
|
+
# under the terms of the MIT License; see LICENSE file for more details.
|
8
|
+
#
|
9
|
+
|
10
|
+
"""Runtime API classes that are returned from the current_runtime instance."""
|
11
|
+
|
12
|
+
from __future__ import annotations
|
13
|
+
|
14
|
+
import dataclasses
|
15
|
+
from functools import cached_property
|
16
|
+
from typing import TYPE_CHECKING, cast
|
17
|
+
|
18
|
+
from flask import current_app
|
19
|
+
from invenio_base.utils import obj_or_import_string
|
20
|
+
from invenio_records_resources.proxies import current_service_registry
|
21
|
+
|
22
|
+
if TYPE_CHECKING:
|
23
|
+
from flask_babel.speaklater import LazyString
|
24
|
+
from flask_resources.responses import ResponseHandler
|
25
|
+
from flask_resources.serializers import BaseSerializer
|
26
|
+
from invenio_drafts_resources.records.api import Draft
|
27
|
+
from invenio_records_resources.records.api import RecordBase
|
28
|
+
from invenio_records_resources.resources.records.config import RecordResourceConfig
|
29
|
+
from invenio_records_resources.resources.records.resource import RecordResource
|
30
|
+
from invenio_records_resources.services import RecordService, RecordServiceConfig
|
31
|
+
|
32
|
+
|
33
|
+
@dataclasses.dataclass
|
34
|
+
class Export:
|
35
|
+
"""Configuration of an export format.
|
36
|
+
|
37
|
+
Exports are shown on the record landing page and user can download them.
|
38
|
+
"""
|
39
|
+
|
40
|
+
name: LazyString
|
41
|
+
"""Name of the export format, human readable."""
|
42
|
+
|
43
|
+
mimetype: str
|
44
|
+
"""MIME type of the export format."""
|
45
|
+
|
46
|
+
serializer: BaseSerializer
|
47
|
+
"""Serializer used to serialize the record into the export format."""
|
48
|
+
|
49
|
+
display: bool = True
|
50
|
+
"""Whether the export format is displayed in the UI."""
|
51
|
+
|
52
|
+
oai_metadata_prefix: str | None = None
|
53
|
+
"""OAI metadata prefix, if applicable. If not set, the export can not be used in OAI-PMH responses."""
|
54
|
+
|
55
|
+
oai_schema: str | None = None
|
56
|
+
"""OAI schema, if applicable. If not set, the export can not be used in OAI-PMH responses."""
|
57
|
+
|
58
|
+
oai_namespace: str | None = None
|
59
|
+
"""OAI namespace, if applicable. If not set, the export can not be used in OAI-PMH responses."""
|
60
|
+
|
61
|
+
|
62
|
+
class Model[
|
63
|
+
S: RecordService = RecordService,
|
64
|
+
C: RecordServiceConfig = RecordServiceConfig,
|
65
|
+
R: RecordBase = RecordBase,
|
66
|
+
D: Draft = Draft,
|
67
|
+
# not sure why this is flagged by pyright as an error
|
68
|
+
RR: RecordResource = RecordResource, # pyright: ignore[reportGeneralTypeIssues]
|
69
|
+
RC: RecordResourceConfig = RecordResourceConfig,
|
70
|
+
]:
|
71
|
+
"""Model configuration.
|
72
|
+
|
73
|
+
Every model in oarepo repository must have this configuration which must be
|
74
|
+
registered in the `oarepo.runtime` extension via the OAREPO_MODELS config
|
75
|
+
variable.
|
76
|
+
"""
|
77
|
+
|
78
|
+
name: str | LazyString
|
79
|
+
"""Name of the model, human readable."""
|
80
|
+
|
81
|
+
version: str
|
82
|
+
"""Version of the model, should be a valid semantic version."""
|
83
|
+
|
84
|
+
description: str | LazyString | None = None
|
85
|
+
"""Description of the model, human readable."""
|
86
|
+
|
87
|
+
records_alias_enabled: bool = False
|
88
|
+
"""Whether the records alias is enabled for this model. Such models will be searchable
|
89
|
+
via the `/api/records` endpoint."""
|
90
|
+
|
91
|
+
def __init__( # noqa: PLR0913 more attributes as we are creating a config
|
92
|
+
self,
|
93
|
+
name: str | LazyString,
|
94
|
+
version: str,
|
95
|
+
service: str | S,
|
96
|
+
resource_config: RC | str,
|
97
|
+
# params with default values
|
98
|
+
service_config: C | None = None,
|
99
|
+
description: str | LazyString | None = None,
|
100
|
+
record: type[R] | None = None,
|
101
|
+
draft: type[D] | None = None,
|
102
|
+
resource: str | RR = "invenio_records_resources.resources.records.resource.RecordResource",
|
103
|
+
exports: list[Export] | None = None,
|
104
|
+
records_alias_enabled: bool = True,
|
105
|
+
):
|
106
|
+
"""Initialize the model configuration.
|
107
|
+
|
108
|
+
:param name: Name of the model, human readable.
|
109
|
+
:param version: Version of the model, should be a valid semantic version.
|
110
|
+
:param description: Description of the model, human readable.
|
111
|
+
:param service: Name of the service inside the `current_service_registry` or
|
112
|
+
a configured service instance.
|
113
|
+
:param service_config: Service configuration, if not provided,
|
114
|
+
if will be taken from the service.
|
115
|
+
:param record: Record class, if not provided, it will be taken from the service
|
116
|
+
configuration.
|
117
|
+
:param draft: Draft class, if not provided, it will be taken from the service
|
118
|
+
configuration.
|
119
|
+
:param resource: Resource class or string import path to the resource class.
|
120
|
+
If not provided, it will be taken from the service configuration.
|
121
|
+
:param resource_config: Resource configuration, if not provided, it will be
|
122
|
+
taken from the resource class.
|
123
|
+
:param exports: List of export formats that can be used to export the record.
|
124
|
+
If not provided, no exports are available.
|
125
|
+
:param records_alias_enabled: Whether the records alias is enabled for this model.
|
126
|
+
Such models will be searchable via the `/api/records` endpoint.
|
127
|
+
"""
|
128
|
+
self.name = name
|
129
|
+
self.version = version
|
130
|
+
self.description = description
|
131
|
+
self.records_alias_enabled = records_alias_enabled
|
132
|
+
|
133
|
+
# lazy getters ...
|
134
|
+
self._record = record
|
135
|
+
self._draft = draft
|
136
|
+
self._service = service
|
137
|
+
self._service_config = service_config
|
138
|
+
self._resource = resource
|
139
|
+
self._resource_config = resource_config
|
140
|
+
self._exports = exports or []
|
141
|
+
|
142
|
+
@property
|
143
|
+
def service(self) -> S:
|
144
|
+
"""Get the service."""
|
145
|
+
if isinstance(self._service, str):
|
146
|
+
return cast(
|
147
|
+
"S",
|
148
|
+
current_service_registry.get(self._service), # type: ignore[attr-defined]
|
149
|
+
)
|
150
|
+
return self._service
|
151
|
+
|
152
|
+
@property
|
153
|
+
def service_config(self) -> C:
|
154
|
+
"""Get the service configuration."""
|
155
|
+
if self._service_config is not None:
|
156
|
+
return self._service_config
|
157
|
+
return cast("C", self.service.config)
|
158
|
+
|
159
|
+
@property
|
160
|
+
def record_cls(self) -> type[R]:
|
161
|
+
"""Get the record class."""
|
162
|
+
if self._record is None:
|
163
|
+
return cast("type[R]", self.service.config.record_cls)
|
164
|
+
return self._record
|
165
|
+
|
166
|
+
@property
|
167
|
+
def draft_cls(self) -> type[D] | None:
|
168
|
+
"""Get the draft class."""
|
169
|
+
if self._draft is None:
|
170
|
+
if hasattr(self.service.config, "draft_cls"):
|
171
|
+
return cast("type[D]", self.service.config.draft_cls)
|
172
|
+
return None
|
173
|
+
return self._draft
|
174
|
+
|
175
|
+
@cached_property
|
176
|
+
def resource_config(self) -> RC:
|
177
|
+
"""Get the resource configuration."""
|
178
|
+
if isinstance(self._resource_config, str):
|
179
|
+
resource_config_class: type[RC] = cast("type[RC]", obj_or_import_string(self._resource_config))
|
180
|
+
# need to import it here to avoid circular import issues
|
181
|
+
from .config import build_config
|
182
|
+
|
183
|
+
return build_config(resource_config_class, current_app)
|
184
|
+
return self._resource_config
|
185
|
+
|
186
|
+
@cached_property
|
187
|
+
def resource(self) -> RR:
|
188
|
+
"""Get the resource."""
|
189
|
+
if isinstance(self._resource, str):
|
190
|
+
resource_class = obj_or_import_string(self._resource)
|
191
|
+
if resource_class is None:
|
192
|
+
raise ValueError(f"Resource class {self._resource} can not be None.")
|
193
|
+
return cast(
|
194
|
+
"RR",
|
195
|
+
resource_class(
|
196
|
+
service=self.service,
|
197
|
+
config=self.resource_config,
|
198
|
+
),
|
199
|
+
)
|
200
|
+
return self._resource
|
201
|
+
|
202
|
+
@property
|
203
|
+
def exports(self) -> list[Export]:
|
204
|
+
"""Get all exportable response handlers."""
|
205
|
+
return self._exports
|
206
|
+
|
207
|
+
@property
|
208
|
+
def response_handlers(self) -> dict[str, ResponseHandler]:
|
209
|
+
"""Get all response handlers from the resource configuration."""
|
210
|
+
return cast("dict[str, ResponseHandler]", self.resource_config.response_handlers)
|
oarepo_runtime/cli/__init__.py
CHANGED
@@ -1,22 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
1
|
+
#
|
2
|
+
# Copyright (c) 2025 CESNET z.s.p.o.
|
3
|
+
#
|
4
|
+
# This file is a part of oarepo-runtime (see http://github.com/oarepo/oarepo-runtime).
|
5
|
+
#
|
6
|
+
# oarepo-runtime is free software; you can redistribute it and/or modify it
|
7
|
+
# under the terms of the MIT License; see LICENSE file for more details.
|
8
|
+
#
|
9
|
+
"""OAREPO Runtime CLI module."""
|
10
10
|
|
11
|
-
|
12
|
-
"oarepo",
|
13
|
-
"index",
|
14
|
-
"as_command",
|
15
|
-
"assets",
|
16
|
-
"check",
|
17
|
-
"validate",
|
18
|
-
"fixtures",
|
19
|
-
"configuration_command",
|
20
|
-
"permissions",
|
21
|
-
"cf",
|
22
|
-
)
|
11
|
+
from __future__ import annotations
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2025 CESNET z.s.p.o.
|
3
|
+
#
|
4
|
+
# This file is a part of oarepo-runtime (see http://github.com/oarepo/oarepo-runtime).
|
5
|
+
#
|
6
|
+
# oarepo-runtime is free software; you can redistribute it and/or modify it
|
7
|
+
# under the terms of the MIT License; see LICENSE file for more details.
|
8
|
+
#
|
9
|
+
"""OARepo extensions to the index command."""
|
10
|
+
|
11
|
+
from __future__ import annotations
|
12
|
+
|
13
|
+
import click
|
14
|
+
from flask.cli import with_appcontext
|
15
|
+
from invenio_search.cli import index, search_version_check
|
16
|
+
from invenio_search.cli import init as original_init
|
17
|
+
|
18
|
+
from oarepo_runtime.services.records.mapping import update_all_records_mappings
|
19
|
+
|
20
|
+
|
21
|
+
@index.command()
|
22
|
+
@click.option("--force", is_flag=True, default=False)
|
23
|
+
@with_appcontext
|
24
|
+
@search_version_check
|
25
|
+
@click.pass_context
|
26
|
+
def init(ctx: click.Context, force: bool) -> None:
|
27
|
+
"""Initialize registered aliases and mappings.
|
28
|
+
|
29
|
+
This command initializes the search indices by creating templates, component templates,
|
30
|
+
index templates, and the actual indices. It will also create all dynamic mappings
|
31
|
+
defined inside the models.
|
32
|
+
"""
|
33
|
+
ctx.invoke(original_init, force=force)
|
34
|
+
update_all_records_mappings()
|
oarepo_runtime/config.py
CHANGED
@@ -1,19 +1,104 @@
|
|
1
|
-
|
1
|
+
#
|
2
|
+
# Copyright (c) 2025 CESNET z.s.p.o.
|
3
|
+
#
|
4
|
+
# This file is a part of oarepo-runtime (see http://github.com/oarepo/oarepo-runtime).
|
5
|
+
#
|
6
|
+
# oarepo-runtime is free software; you can redistribute it and/or modify it
|
7
|
+
# under the terms of the MIT License; see LICENSE file for more details.
|
8
|
+
#
|
2
9
|
|
3
|
-
|
10
|
+
"""Config module."""
|
4
11
|
|
12
|
+
from __future__ import annotations
|
5
13
|
|
6
|
-
|
7
|
-
|
8
|
-
|
14
|
+
from typing import TYPE_CHECKING, Any
|
15
|
+
|
16
|
+
from invenio_vocabularies import __version__ as vocabularies_version
|
17
|
+
|
18
|
+
from .api import Model
|
19
|
+
|
20
|
+
if TYPE_CHECKING:
|
21
|
+
from collections.abc import Callable
|
22
|
+
|
23
|
+
from flask import Flask
|
9
24
|
|
10
|
-
|
25
|
+
|
26
|
+
def build_config[T](config_class: type[T], app: Flask, *args: Any, **kwargs: Any) -> T:
|
27
|
+
"""Build the configuration for the service.
|
28
|
+
|
29
|
+
This function is used to build the configuration for the service.
|
11
30
|
"""
|
12
|
-
|
31
|
+
build_config: Callable[[Flask], T] | None = getattr(config_class, "build", None)
|
32
|
+
if build_config is not None and callable(build_config):
|
13
33
|
if args or kwargs:
|
14
|
-
raise ValueError(
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
34
|
+
raise ValueError("Can not pass extra arguments when invenio ConfigMixin is used")
|
35
|
+
return build_config(app)
|
36
|
+
return config_class(*args, **kwargs)
|
37
|
+
|
38
|
+
|
39
|
+
#
|
40
|
+
# Configuration for the extension.
|
41
|
+
#
|
42
|
+
|
43
|
+
OAREPO_MODELS: dict[str, Model] = {
|
44
|
+
# default invenio vocabularies
|
45
|
+
"vocabularies": Model(
|
46
|
+
name="vocabularies",
|
47
|
+
version=vocabularies_version,
|
48
|
+
service="vocabularies",
|
49
|
+
description="Base (non-specialized) invenio vocabularies",
|
50
|
+
records_alias_enabled=False,
|
51
|
+
resource_config="invenio_vocabularies.resources.config.VocabulariesResourceConfig",
|
52
|
+
resource="invenio_vocabularies.resources.resource.VocabulariesResource",
|
53
|
+
),
|
54
|
+
# affiliations
|
55
|
+
"affiliations": Model(
|
56
|
+
name="affiliations",
|
57
|
+
version=vocabularies_version,
|
58
|
+
service="affiliations",
|
59
|
+
description="Affiliations vocabulary",
|
60
|
+
records_alias_enabled=False,
|
61
|
+
resource_config="invenio_vocabularies.contrib.affiliations.resources.AffiliationsResourceConfig",
|
62
|
+
resource="invenio_vocabularies.contrib.affiliations.resources.AffiliationsResource",
|
63
|
+
),
|
64
|
+
# funders
|
65
|
+
"funders": Model(
|
66
|
+
name="funders",
|
67
|
+
version=vocabularies_version,
|
68
|
+
service="funders",
|
69
|
+
description="Funders vocabulary",
|
70
|
+
records_alias_enabled=False,
|
71
|
+
resource_config="invenio_vocabularies.contrib.funders.resources.FundersResourceConfig",
|
72
|
+
resource="invenio_vocabularies.contrib.funders.resources.FundersResource",
|
73
|
+
),
|
74
|
+
# awards
|
75
|
+
"awards": Model(
|
76
|
+
name="awards",
|
77
|
+
version=vocabularies_version,
|
78
|
+
service="awards",
|
79
|
+
description="Awards vocabulary",
|
80
|
+
records_alias_enabled=False,
|
81
|
+
resource_config="invenio_vocabularies.contrib.awards.resources.AwardsResourceConfig",
|
82
|
+
resource="invenio_vocabularies.contrib.awards.resources.AwardsResource",
|
83
|
+
),
|
84
|
+
# names
|
85
|
+
"names": Model(
|
86
|
+
name="names",
|
87
|
+
version=vocabularies_version,
|
88
|
+
service="names",
|
89
|
+
description="Names vocabulary",
|
90
|
+
records_alias_enabled=False,
|
91
|
+
resource_config="invenio_vocabularies.contrib.names.resources.NamesResourceConfig",
|
92
|
+
resource="invenio_vocabularies.contrib.names.resources.NamesResource",
|
93
|
+
),
|
94
|
+
# subjects
|
95
|
+
"subjects": Model(
|
96
|
+
name="subjects",
|
97
|
+
version=vocabularies_version,
|
98
|
+
service="subjects",
|
99
|
+
description="Subjects vocabulary",
|
100
|
+
records_alias_enabled=False,
|
101
|
+
resource_config="invenio_vocabularies.contrib.subjects.resources.SubjectsResourceConfig",
|
102
|
+
resource="invenio_vocabularies.contrib.subjects.resources.SubjectsResource",
|
103
|
+
),
|
104
|
+
}
|
oarepo_runtime/ext.py
CHANGED
@@ -1,102 +1,84 @@
|
|
1
|
-
|
1
|
+
#
|
2
|
+
# Copyright (c) 2025 CESNET z.s.p.o.
|
3
|
+
#
|
4
|
+
# This file is a part of oarepo-runtime (see http://github.com/oarepo/oarepo-runtime).
|
5
|
+
#
|
6
|
+
# oarepo-runtime is free software; you can redistribute it and/or modify it
|
7
|
+
# under the terms of the MIT License; see LICENSE file for more details.
|
8
|
+
#
|
9
|
+
|
10
|
+
"""Extension preset for runtime module."""
|
2
11
|
|
3
|
-
import
|
4
|
-
from flask import current_app, session
|
5
|
-
from invenio_accounts.models import User
|
6
|
-
from invenio_base.utils import obj_or_import_string
|
12
|
+
from __future__ import annotations
|
7
13
|
|
8
|
-
from
|
9
|
-
from
|
10
|
-
from .proxies import current_timezone
|
14
|
+
from functools import cached_property
|
15
|
+
from typing import TYPE_CHECKING, Any, cast
|
11
16
|
|
17
|
+
from flask import current_app
|
18
|
+
from invenio_records_resources.proxies import current_service_registry
|
19
|
+
from invenio_records_resources.records.api import RecordBase
|
12
20
|
|
13
|
-
|
14
|
-
if "timezone" in session:
|
15
|
-
current_timezone.set(pytz.timezone(session["timezone"]))
|
16
|
-
else:
|
17
|
-
default_user_timezone = current_app.config.get("BABEL_DEFAULT_TIMEZONE")
|
18
|
-
if default_user_timezone:
|
19
|
-
current_timezone.set(pytz.timezone(default_user_timezone))
|
20
|
-
else:
|
21
|
-
current_timezone.set(None)
|
21
|
+
from . import config
|
22
22
|
|
23
|
+
if TYPE_CHECKING: # pragma: no cover
|
24
|
+
from flask import Flask
|
25
|
+
from invenio_records_resources.services.base.service import Service
|
26
|
+
from invenio_records_resources.services.records import RecordService
|
23
27
|
|
24
|
-
|
25
|
-
if "timezone" not in session and "_user_id" in session:
|
26
|
-
user = User.query.filter_by(id=session["_user_id"]).first()
|
27
|
-
if user and "timezone" in user.preferences:
|
28
|
-
session["timezone"] = user.preferences["timezone"]
|
29
|
-
set_timezone()
|
28
|
+
from .api import Model
|
30
29
|
|
31
30
|
|
32
|
-
class OARepoRuntime
|
33
|
-
"""OARepo
|
31
|
+
class OARepoRuntime:
|
32
|
+
"""OARepo base of invenio oarepo client."""
|
34
33
|
|
35
|
-
def __init__(self, app=None):
|
34
|
+
def __init__(self, app: Flask | None = None):
|
36
35
|
"""Extension initialization."""
|
37
36
|
if app:
|
38
37
|
self.init_app(app)
|
39
38
|
|
40
|
-
def init_app(self, app):
|
39
|
+
def init_app(self, app: Flask) -> None:
|
41
40
|
"""Flask application initialization."""
|
42
|
-
self.init_config(app)
|
43
41
|
self.app = app
|
42
|
+
self.init_config(app)
|
44
43
|
app.extensions["oarepo-runtime"] = self
|
45
|
-
app.extensions["oarepo-datastreams"] = OARepoDataStreamsExt(app)
|
46
|
-
app.cli.add_command(oarepo_cmd)
|
47
|
-
|
48
|
-
from flask_principal import identity_changed
|
49
44
|
|
50
|
-
|
51
|
-
|
45
|
+
def init_config(self, app: Flask) -> None:
|
46
|
+
"""Initialize the configuration for the extension."""
|
47
|
+
app.config.setdefault("OAREPO_MODELS", {})
|
48
|
+
for k, v in config.OAREPO_MODELS.items():
|
49
|
+
if k not in app.config["OAREPO_MODELS"]:
|
50
|
+
app.config["OAREPO_MODELS"][k] = v
|
52
51
|
|
53
|
-
@
|
54
|
-
def
|
55
|
-
|
56
|
-
|
57
|
-
]
|
52
|
+
@property
|
53
|
+
def models(self) -> dict[str, Model]:
|
54
|
+
"""Return the models registered in the extension."""
|
55
|
+
return cast("dict[str, Model]", current_app.config["OAREPO_MODELS"])
|
58
56
|
|
59
57
|
@cached_property
|
60
|
-
def
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
for
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
else:
|
88
|
-
app.config.setdefault(k, val)
|
89
|
-
|
90
|
-
elif k == "HAS_DRAFT_CUSTOM_FIELD":
|
91
|
-
app.config.setdefault(k, getattr(ext_config, k))
|
92
|
-
|
93
|
-
elif k == "OAREPO_FACET_GROUP_NAME":
|
94
|
-
app.config.setdefault(k, getattr(ext_config, k))
|
95
|
-
|
96
|
-
elif k == "OWNER_ENTITY_RESOLVERS":
|
97
|
-
app.config.setdefault(k, []).extend(getattr(ext_config, k))
|
98
|
-
|
99
|
-
def add_non_existing(self, target, source):
|
100
|
-
for val_k, val_value in source.items():
|
101
|
-
if val_k not in target:
|
102
|
-
target[val_k] = val_value
|
58
|
+
def models_by_record_class(self) -> dict[type[RecordBase], Model]:
|
59
|
+
"""Return a mapping of record classes to their models."""
|
60
|
+
ret = {model.record_cls: model for model in self.models.values() if model.record_cls is not None}
|
61
|
+
ret.update({model.draft_cls: model for model in self.models.values() if model.draft_cls is not None})
|
62
|
+
return ret
|
63
|
+
|
64
|
+
@property
|
65
|
+
def services(self) -> dict[str, Service]:
|
66
|
+
"""Return the services registered in the extension."""
|
67
|
+
_services = current_service_registry._services # type: ignore[attr-defined] # noqa: SLF001
|
68
|
+
return cast("dict[str, Service]", _services)
|
69
|
+
|
70
|
+
def get_record_service_for_record(self, record: Any) -> RecordService:
|
71
|
+
"""Retrieve the associated service for a given record."""
|
72
|
+
if record is None:
|
73
|
+
raise ValueError("Need to pass a record instance, got None")
|
74
|
+
return self.get_record_service_for_record_class(type(record))
|
75
|
+
|
76
|
+
def get_record_service_for_record_class(self, record_cls: type[RecordBase]) -> RecordService:
|
77
|
+
"""Retrieve the service associated with a given record class."""
|
78
|
+
for t in record_cls.mro():
|
79
|
+
if t is RecordBase:
|
80
|
+
break
|
81
|
+
if t in self.models_by_record_class:
|
82
|
+
model = self.models_by_record_class[t]
|
83
|
+
return model.service
|
84
|
+
raise KeyError(f"No service found for record class '{record_cls.__name__}'.")
|
oarepo_runtime/proxies.py
CHANGED
@@ -1,8 +1,24 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2025 CESNET z.s.p.o.
|
3
|
+
#
|
4
|
+
# This file is a part of oarepo-runtime (see http://github.com/oarepo/oarepo-runtime).
|
5
|
+
#
|
6
|
+
# oarepo-runtime is free software; you can redistribute it and/or modify it
|
7
|
+
# under the terms of the MIT License; see LICENSE file for more details.
|
8
|
+
#
|
9
|
+
|
10
|
+
"""Proxies."""
|
11
|
+
|
12
|
+
from __future__ import annotations
|
13
|
+
|
14
|
+
from typing import TYPE_CHECKING
|
15
|
+
|
1
16
|
from flask import current_app
|
2
17
|
from werkzeug.local import LocalProxy
|
3
|
-
from contextvars import ContextVar
|
4
18
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
19
|
+
if TYPE_CHECKING:
|
20
|
+
from oarepo_runtime.ext import OARepoRuntime
|
21
|
+
|
22
|
+
current_runtime: OARepoRuntime
|
23
|
+
|
24
|
+
current_runtime = LocalProxy(lambda: current_app.extensions["oarepo-runtime"]) # type: ignore[assignment]
|