oarepo-runtime 2.0.0.dev18__tar.gz → 2.0.0.dev20__tar.gz
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-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/PKG-INFO +1 -1
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/__init__.py +1 -1
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/api.py +13 -5
- oarepo_runtime-2.0.0.dev20/oarepo_runtime/records/systemfields/custom_fields.py +63 -0
- oarepo_runtime-2.0.0.dev20/oarepo_runtime/records/systemfields/selectors.py +51 -0
- oarepo_runtime-2.0.0.dev20/oarepo_runtime/services/records/custom_fields.py +44 -0
- oarepo_runtime-2.0.0.dev20/oarepo_runtime/typing.py +60 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/.gitignore +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/LICENSE +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/README.md +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/cli/__init__.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/cli/search.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/config.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/ext.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/proxies.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/py.typed +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/records/__init__.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/records/drafts.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/records/mapping.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/records/pid_providers.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/records/systemfields/__init__.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/records/systemfields/mapping.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/records/systemfields/publication_status.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/resources/__init__.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/resources/config.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/__init__.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/config/__init__.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/config/components.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/config/link_conditions.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/config/permissions.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/facets/__init__.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/facets/params.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/generators.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/records/__init__.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/records/links.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/records/mapping.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/results.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/schema/__init__.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/schema/i18n.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/schema/i18n_ui.py +0 -0
- {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/pyproject.toml +0 -0
@@ -126,16 +126,17 @@ class Model[
|
|
126
126
|
exports: list[Export] | None = None,
|
127
127
|
records_alias_enabled: bool = True,
|
128
128
|
model_metadata: ModelMetadata | None = None,
|
129
|
+
features: Mapping[str, Any] | None = None,
|
129
130
|
):
|
130
131
|
"""Initialize the model configuration.
|
131
132
|
|
132
|
-
:param name: Name of the model, human
|
133
|
-
:param version: Version of the model
|
134
|
-
:param description: Description of the model, human
|
133
|
+
:param name: Name of the model, human-readable.
|
134
|
+
:param version: Version of the model should be a valid semantic version.
|
135
|
+
:param description: Description of the model, human-readable.
|
135
136
|
:param service: Name of the service inside the `current_service_registry` or
|
136
137
|
a configured service instance.
|
137
138
|
:param service_config: Service configuration, if not provided,
|
138
|
-
|
139
|
+
it will be taken from the service.
|
139
140
|
:param record: Record class, if not provided, it will be taken from the service
|
140
141
|
configuration.
|
141
142
|
:param draft: Draft class, if not provided, it will be taken from the service
|
@@ -146,9 +147,10 @@ class Model[
|
|
146
147
|
taken from the resource class.
|
147
148
|
:param exports: List of export formats that can be used to export the record.
|
148
149
|
If not provided, no exports are available.
|
149
|
-
:param records_alias_enabled: Whether the
|
150
|
+
:param records_alias_enabled: Whether the record alias is enabled for this model.
|
150
151
|
Such models will be searchable via the `/api/records` endpoint.
|
151
152
|
:param model_metadata: Metadata of the model.
|
153
|
+
:param features: Features of the model. Filled by the feature presets themselves during registration.
|
152
154
|
"""
|
153
155
|
self._code = code
|
154
156
|
self._name = name
|
@@ -171,6 +173,7 @@ class Model[
|
|
171
173
|
self._resource_config = resource_config
|
172
174
|
self._exports = exports or []
|
173
175
|
self._model_metadata = model_metadata
|
176
|
+
self._features = features
|
174
177
|
|
175
178
|
@property
|
176
179
|
def code(self) -> str:
|
@@ -342,3 +345,8 @@ class Model[
|
|
342
345
|
def response_handlers(self) -> dict[str, ResponseHandler]:
|
343
346
|
"""Get all response handlers from the resource configuration."""
|
344
347
|
return cast("dict[str, ResponseHandler]", self.resource_config.response_handlers)
|
348
|
+
|
349
|
+
@property
|
350
|
+
def features(self) -> Mapping[str, Any] | None:
|
351
|
+
"""Get a mapping of features."""
|
352
|
+
return self._features
|
@@ -0,0 +1,63 @@
|
|
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
|
+
"""Module to update the mapping of system fields in a record class."""
|
10
|
+
|
11
|
+
from __future__ import annotations
|
12
|
+
|
13
|
+
import inspect
|
14
|
+
from typing import TYPE_CHECKING
|
15
|
+
|
16
|
+
from flask import current_app
|
17
|
+
from invenio_records.systemfields.relations import MultiRelationsField
|
18
|
+
from invenio_vocabularies.records.systemfields.relations import CustomFieldsRelation
|
19
|
+
|
20
|
+
from oarepo_runtime.records.mapping import prefixed_index, update_record_index
|
21
|
+
|
22
|
+
if TYPE_CHECKING:
|
23
|
+
from collections.abc import Iterable
|
24
|
+
|
25
|
+
from invenio_records.api import RecordBase
|
26
|
+
|
27
|
+
|
28
|
+
def update_record_system_fields_mapping_relation_field(
|
29
|
+
record_class: type[RecordBase],
|
30
|
+
) -> None:
|
31
|
+
"""Update mapping for system fields in the record class.
|
32
|
+
|
33
|
+
:param record_class: The record class which index mapping should be updated.
|
34
|
+
:raise search.RequestError: If there is an error while updating the mapping.
|
35
|
+
"""
|
36
|
+
index = getattr(record_class, "index", None)
|
37
|
+
if not index:
|
38
|
+
return
|
39
|
+
|
40
|
+
for field_name, fld in get_mapping_relation_fields(record_class):
|
41
|
+
custom_fields = current_app.config.get(fld._fields_var, []) # noqa: SLF001
|
42
|
+
|
43
|
+
props: dict[str, dict] = {}
|
44
|
+
mapping = {field_name: {"type": "object", "properties": props}}
|
45
|
+
for cf in custom_fields:
|
46
|
+
# get mapping
|
47
|
+
props[cf.name] = cf.mapping
|
48
|
+
|
49
|
+
# upload mapping
|
50
|
+
if props:
|
51
|
+
update_record_index(prefixed_index(index), {}, mapping, None)
|
52
|
+
|
53
|
+
|
54
|
+
def get_mapping_relation_fields(
|
55
|
+
record_class: type[RecordBase],
|
56
|
+
) -> Iterable[tuple[str, CustomFieldsRelation]]:
|
57
|
+
"""Get all mapping fields from the record class."""
|
58
|
+
for _, relation_fields in inspect.getmembers(record_class, lambda x: isinstance(x, MultiRelationsField)):
|
59
|
+
yield from (
|
60
|
+
(field_name, relation_field)
|
61
|
+
for field_name, relation_field in relation_fields._original_fields.items() # noqa: SLF001
|
62
|
+
if isinstance(relation_field, CustomFieldsRelation)
|
63
|
+
)
|
@@ -0,0 +1,51 @@
|
|
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
|
+
"""Selectors for extracting values from records based on specified paths."""
|
10
|
+
|
11
|
+
from __future__ import annotations
|
12
|
+
|
13
|
+
from typing import Any, Protocol
|
14
|
+
|
15
|
+
|
16
|
+
class Selector(Protocol):
|
17
|
+
"""Protocol for selectors that extract values from records."""
|
18
|
+
|
19
|
+
def select(self, record: dict) -> list[Any]: # noqa: ARG002
|
20
|
+
"""Select values from the record based on the selector's logic."""
|
21
|
+
return []
|
22
|
+
|
23
|
+
|
24
|
+
class PathSelector(Selector):
|
25
|
+
"""Selector that extracts values from records based on specified paths."""
|
26
|
+
|
27
|
+
def __init__(self, *paths: str) -> None:
|
28
|
+
"""Initialize the PathSelector with given paths."""
|
29
|
+
self.paths = [x.split(".") for x in paths]
|
30
|
+
|
31
|
+
def select(self, record: dict) -> list[Any]:
|
32
|
+
"""Select values from the record based on the specified paths."""
|
33
|
+
ret = []
|
34
|
+
for path in self.paths:
|
35
|
+
ret.extend(list(getter(record, path)))
|
36
|
+
return ret
|
37
|
+
|
38
|
+
|
39
|
+
def getter(data: list | dict, path: list) -> Any:
|
40
|
+
"""Recursively get values from data based on the provided path."""
|
41
|
+
if len(path) == 0:
|
42
|
+
if isinstance(data, list):
|
43
|
+
yield from data
|
44
|
+
else:
|
45
|
+
yield data
|
46
|
+
elif isinstance(data, dict):
|
47
|
+
if path[0] in data:
|
48
|
+
yield from getter(data[path[0]], path[1:])
|
49
|
+
elif isinstance(data, list):
|
50
|
+
for item in data:
|
51
|
+
yield from getter(item, path)
|
@@ -0,0 +1,44 @@
|
|
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
|
+
"""Services for updating custom fields mappings in opensearch."""
|
10
|
+
|
11
|
+
from __future__ import annotations
|
12
|
+
|
13
|
+
from typing import TYPE_CHECKING
|
14
|
+
|
15
|
+
from invenio_records_resources.services.records import (
|
16
|
+
RecordService,
|
17
|
+
RecordServiceConfig,
|
18
|
+
)
|
19
|
+
|
20
|
+
from oarepo_runtime import current_runtime
|
21
|
+
from oarepo_runtime.records.systemfields.custom_fields import (
|
22
|
+
update_record_system_fields_mapping_relation_field,
|
23
|
+
)
|
24
|
+
|
25
|
+
if TYPE_CHECKING:
|
26
|
+
from invenio_records_resources.services.base import Service
|
27
|
+
|
28
|
+
|
29
|
+
def update_all_records_mappings_relation_fields() -> None:
|
30
|
+
"""Update all mappings for the registered record classes."""
|
31
|
+
service: Service
|
32
|
+
for service in current_runtime.services.values():
|
33
|
+
if not isinstance(service, RecordService):
|
34
|
+
continue
|
35
|
+
|
36
|
+
config: RecordServiceConfig = service.config
|
37
|
+
|
38
|
+
record_class = getattr(config, "record_cls", None)
|
39
|
+
if record_class:
|
40
|
+
update_record_system_fields_mapping_relation_field(record_class)
|
41
|
+
|
42
|
+
draft_class = getattr(config, "draft_cls", None)
|
43
|
+
if draft_class:
|
44
|
+
update_record_system_fields_mapping_relation_field(draft_class)
|
@@ -0,0 +1,60 @@
|
|
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
|
+
"""Module for typing related functionality."""
|
11
|
+
|
12
|
+
from __future__ import annotations
|
13
|
+
|
14
|
+
from typing import TYPE_CHECKING, Any
|
15
|
+
|
16
|
+
if TYPE_CHECKING:
|
17
|
+
from collections.abc import Callable
|
18
|
+
|
19
|
+
|
20
|
+
def require_kwargs(*kwargs_names: str) -> Any:
|
21
|
+
"""Wrap function to require specific kwargs in a function call.
|
22
|
+
|
23
|
+
This decorator is used to fix typing errors in inherited classes where the base class defines kwargs and the
|
24
|
+
inherited class needs to access a specific kwarg.
|
25
|
+
|
26
|
+
Example:
|
27
|
+
```python
|
28
|
+
# base class
|
29
|
+
class ConditionalGenerator(
|
30
|
+
InvenioConditionalGenerator, ABC
|
31
|
+
):
|
32
|
+
@abstractmethod
|
33
|
+
def _condition(
|
34
|
+
self, **kwargs: Any
|
35
|
+
) -> bool: ...
|
36
|
+
|
37
|
+
|
38
|
+
# inherited class
|
39
|
+
class IfRecordHasField(
|
40
|
+
ConditionalGenerator
|
41
|
+
):
|
42
|
+
@override
|
43
|
+
@require_kwargs("field")
|
44
|
+
def _condition(
|
45
|
+
self, *, field, **kwargs: Any
|
46
|
+
) -> bool: ...
|
47
|
+
```
|
48
|
+
|
49
|
+
"""
|
50
|
+
|
51
|
+
def wrapper(f: Callable) -> Callable:
|
52
|
+
def wrapped_f(*args: Any, **kwargs: Any) -> Any:
|
53
|
+
for kwarg_name in kwargs_names:
|
54
|
+
if kwarg_name not in kwargs:
|
55
|
+
raise ValueError(f"Keyword argument {kwarg_name} not found in function call.")
|
56
|
+
return f(*args, **kwargs)
|
57
|
+
|
58
|
+
return wrapped_f
|
59
|
+
|
60
|
+
return wrapper
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/records/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/records/pid_providers.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/resources/__init__.py
RENAMED
File without changes
|
{oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/resources/config.py
RENAMED
File without changes
|
{oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/__init__.py
RENAMED
File without changes
|
{oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/config/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/facets/__init__.py
RENAMED
File without changes
|
{oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/facets/params.py
RENAMED
File without changes
|
{oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/generators.py
RENAMED
File without changes
|
File without changes
|
{oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/records/links.py
RENAMED
File without changes
|
{oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/records/mapping.py
RENAMED
File without changes
|
{oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/results.py
RENAMED
File without changes
|
{oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/schema/__init__.py
RENAMED
File without changes
|
{oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/schema/i18n.py
RENAMED
File without changes
|
{oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev20}/oarepo_runtime/services/schema/i18n_ui.py
RENAMED
File without changes
|
File without changes
|