oarepo-runtime 1.10.2__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.2.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.2.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 -75
- 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 -85
- 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 -89
- oarepo_runtime/translations/messages.pot +0 -91
- 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.2.dist-info/RECORD +0 -163
- oarepo_runtime-1.10.2.dist-info/entry_points.txt +0 -16
- oarepo_runtime-1.10.2.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.2.dist-info → oarepo_runtime-2.0.0.dev3.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.0dev3"
|
23
|
+
|
24
|
+
__all__ = ("Model", "OARepoRuntime", "__version__", "current_runtime")
|
oarepo_runtime/api.py
ADDED
@@ -0,0 +1,111 @@
|
|
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
|
+
from typing import TYPE_CHECKING, cast
|
15
|
+
|
16
|
+
from invenio_records_resources.proxies import current_service_registry
|
17
|
+
|
18
|
+
if TYPE_CHECKING:
|
19
|
+
from flask_babel.speaklater import LazyString
|
20
|
+
from invenio_drafts_resources.records.api import Draft
|
21
|
+
from invenio_records_resources.records.api import RecordBase
|
22
|
+
from invenio_records_resources.services import RecordService, RecordServiceConfig
|
23
|
+
|
24
|
+
|
25
|
+
class Model[
|
26
|
+
S: RecordService = RecordService,
|
27
|
+
C: RecordServiceConfig = RecordServiceConfig,
|
28
|
+
R: RecordBase = RecordBase,
|
29
|
+
D: Draft = Draft,
|
30
|
+
]:
|
31
|
+
"""Model configuration.
|
32
|
+
|
33
|
+
Every model in oarepo repository must have this configuration which must be
|
34
|
+
registered in the `oarepo.runtime` extension via the OAREPO_MODELS config
|
35
|
+
variable.
|
36
|
+
"""
|
37
|
+
|
38
|
+
name: str | LazyString
|
39
|
+
version: str
|
40
|
+
description: str | LazyString | None = None
|
41
|
+
global_search_enabled: bool = False
|
42
|
+
|
43
|
+
def __init__( # noqa: PLR0913 more attributes as we are creating a config
|
44
|
+
self,
|
45
|
+
name: str | LazyString,
|
46
|
+
version: str,
|
47
|
+
service: str | S,
|
48
|
+
# params with default values
|
49
|
+
service_config: C | None = None,
|
50
|
+
description: str | LazyString | None = None,
|
51
|
+
record: type[R] | None = None,
|
52
|
+
draft: type[D] | None = None,
|
53
|
+
global_search_enabled: bool = True,
|
54
|
+
):
|
55
|
+
"""Initialize the model configuration.
|
56
|
+
|
57
|
+
:param name: Name of the model, human readable.
|
58
|
+
:param version: Version of the model, should be a valid semantic version.
|
59
|
+
:param description: Description of the model, human readable.
|
60
|
+
:param service: Name of the service inside the `current_service_registry` or
|
61
|
+
a configured service instance.
|
62
|
+
:param service_config: Service configuration, if not provided,
|
63
|
+
if will be taken from the service.
|
64
|
+
:param record: Record class, if not provided, it will be taken from the service
|
65
|
+
configuration.
|
66
|
+
:param draft: Draft class, if not provided, it will be taken from the service
|
67
|
+
configuration.
|
68
|
+
"""
|
69
|
+
self.name = name
|
70
|
+
self.version = version
|
71
|
+
self.description = description
|
72
|
+
self.global_search_enabled = global_search_enabled
|
73
|
+
|
74
|
+
# lazy getters ...
|
75
|
+
self._record = record
|
76
|
+
self._draft = draft
|
77
|
+
self._service = service
|
78
|
+
self._service_config = service_config
|
79
|
+
|
80
|
+
@property
|
81
|
+
def service(self) -> S:
|
82
|
+
"""Get the service."""
|
83
|
+
if isinstance(self._service, str):
|
84
|
+
return cast(
|
85
|
+
"S",
|
86
|
+
current_service_registry.get(self._service), # type: ignore[attr-defined]
|
87
|
+
)
|
88
|
+
return self._service
|
89
|
+
|
90
|
+
@property
|
91
|
+
def service_config(self) -> C:
|
92
|
+
"""Get the service configuration."""
|
93
|
+
if self._service_config is not None:
|
94
|
+
return self._service_config
|
95
|
+
return cast("C", self.service.config)
|
96
|
+
|
97
|
+
@property
|
98
|
+
def record_cls(self) -> type[R]:
|
99
|
+
"""Get the record class."""
|
100
|
+
if self._record is None:
|
101
|
+
return cast("type[R]", self.service.config.record_cls)
|
102
|
+
return self._record
|
103
|
+
|
104
|
+
@property
|
105
|
+
def draft_cls(self) -> type[D] | None:
|
106
|
+
"""Get the draft class."""
|
107
|
+
if self._draft is None:
|
108
|
+
if hasattr(self.service.config, "draft_cls"):
|
109
|
+
return cast("type[D]", self.service.config.draft_cls)
|
110
|
+
return None
|
111
|
+
return self._draft
|
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,92 @@
|
|
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
|
+
global_search_enabled=False,
|
51
|
+
),
|
52
|
+
# affiliations
|
53
|
+
"affiliations": Model(
|
54
|
+
name="affiliations",
|
55
|
+
version=vocabularies_version,
|
56
|
+
service="affiliations",
|
57
|
+
description="Affiliations vocabulary",
|
58
|
+
global_search_enabled=False,
|
59
|
+
),
|
60
|
+
# funders
|
61
|
+
"funders": Model(
|
62
|
+
name="funders",
|
63
|
+
version=vocabularies_version,
|
64
|
+
service="funders",
|
65
|
+
description="Funders vocabulary",
|
66
|
+
global_search_enabled=False,
|
67
|
+
),
|
68
|
+
# awards
|
69
|
+
"awards": Model(
|
70
|
+
name="awards",
|
71
|
+
version=vocabularies_version,
|
72
|
+
service="awards",
|
73
|
+
description="Awards vocabulary",
|
74
|
+
global_search_enabled=False,
|
75
|
+
),
|
76
|
+
# names
|
77
|
+
"names": Model(
|
78
|
+
name="names",
|
79
|
+
version=vocabularies_version,
|
80
|
+
service="names",
|
81
|
+
description="Names vocabulary",
|
82
|
+
global_search_enabled=False,
|
83
|
+
),
|
84
|
+
# subjects
|
85
|
+
"subjects": Model(
|
86
|
+
name="subjects",
|
87
|
+
version=vocabularies_version,
|
88
|
+
service="subjects",
|
89
|
+
description="Subjects vocabulary",
|
90
|
+
global_search_enabled=False,
|
91
|
+
),
|
92
|
+
}
|
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]
|
@@ -1,50 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
return record_cls(obj.data, model=obj)
|
13
|
-
|
14
|
-
|
15
|
-
@deprecated("Moved to oarepo_runtime.services.config.link_conditions")
|
16
|
-
def is_published_record_function():
|
17
|
-
"""Shortcut for links to determine if record is a published.
|
18
|
-
|
19
|
-
This function is deprecated. Use oarepo_runtime.services.config.is_published_record instead.
|
20
|
-
"""
|
21
|
-
from oarepo_runtime.services.config.link_conditions import is_published_record
|
22
|
-
|
23
|
-
return is_published_record()
|
24
|
-
|
25
|
-
|
26
|
-
@deprecated("Moved to oarepo_runtime.services.config.link_conditions")
|
27
|
-
def is_draft_record_function():
|
28
|
-
"""Shortcut for links to determine if record is a draft record.
|
29
|
-
|
30
|
-
This function is deprecated. Use oarepo_runtime.services.config.is_draft_record instead.
|
31
|
-
"""
|
32
|
-
from oarepo_runtime.services.config.link_conditions import is_draft_record
|
33
|
-
|
34
|
-
return is_draft_record()
|
35
|
-
|
36
|
-
|
37
|
-
@deprecated("Moved to oarepo_runtime.services.config.link_conditions")
|
38
|
-
def has_draft_function():
|
39
|
-
"""Shortcut for links to determine if record is either a draft or a published one with a draft associated.
|
40
|
-
|
41
|
-
This function is deprecated. Use oarepo_runtime.services.config.has_draft instead.
|
42
|
-
"""
|
43
|
-
from oarepo_runtime.services.config.link_conditions import has_draft
|
44
|
-
|
45
|
-
return has_draft()
|
46
|
-
|
47
|
-
|
48
|
-
is_published_record = is_published_record_function()
|
49
|
-
is_draft = is_draft_record_function()
|
50
|
-
has_draft = has_draft_function()
|
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
|
+
"""Records module."""
|
10
|
+
|
11
|
+
from __future__ import annotations
|
oarepo_runtime/records/drafts.py
CHANGED
@@ -1,13 +1,29 @@
|
|
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
|
+
"""Record drafts."""
|
2
10
|
|
3
|
-
from
|
11
|
+
from __future__ import annotations
|
4
12
|
|
13
|
+
from typing import TYPE_CHECKING
|
5
14
|
|
6
|
-
|
15
|
+
if TYPE_CHECKING:
|
16
|
+
from invenio_records_resources.records.api import RecordBase
|
17
|
+
|
18
|
+
from oarepo_runtime.proxies import current_runtime
|
19
|
+
|
20
|
+
|
21
|
+
def has_draft(record: RecordBase) -> bool:
|
22
|
+
"""Check if record has draft."""
|
7
23
|
return get_draft(record) is not None
|
8
24
|
|
9
25
|
|
10
|
-
def get_draft(record:
|
26
|
+
def get_draft(record: RecordBase) -> RecordBase | None:
|
11
27
|
"""Get the draft of a published record, if it exists.
|
12
28
|
|
13
29
|
A record can have a draft if:
|
@@ -19,24 +35,14 @@ def get_draft(record: Record) -> Record | None:
|
|
19
35
|
"""
|
20
36
|
if getattr(record, "is_draft", False):
|
21
37
|
return record
|
22
|
-
if not hasattr(record, "parent"):
|
23
|
-
return None
|
24
|
-
if not hasattr(record, "has_draft"):
|
38
|
+
if not hasattr(record, "parent") or not hasattr(record, "has_draft"):
|
25
39
|
return None
|
26
40
|
|
27
|
-
record_service = get_record_service_for_record(record)
|
28
|
-
if not record_service:
|
29
|
-
return None
|
41
|
+
record_service = current_runtime.get_record_service_for_record(record)
|
30
42
|
|
31
43
|
try:
|
32
|
-
|
33
|
-
|
34
|
-
return None
|
35
|
-
return next(
|
36
|
-
record_service.config.draft_cls.get_records_by_parent(
|
37
|
-
record.parent, with_deleted=False
|
38
|
-
)
|
39
|
-
)
|
44
|
+
parent = getattr(record, "parent", None)
|
45
|
+
return next(record_service.config.draft_cls.get_records_by_parent(parent, with_deleted=False))
|
40
46
|
except StopIteration:
|
41
47
|
# no draft found
|
42
48
|
return None
|