oarepo-runtime 2.0.0.dev18__tar.gz → 2.0.0.dev19__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.
Files changed (41) hide show
  1. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/PKG-INFO +1 -1
  2. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/__init__.py +1 -1
  3. oarepo_runtime-2.0.0.dev19/oarepo_runtime/records/systemfields/custom_fields.py +63 -0
  4. oarepo_runtime-2.0.0.dev19/oarepo_runtime/records/systemfields/selectors.py +51 -0
  5. oarepo_runtime-2.0.0.dev19/oarepo_runtime/services/records/custom_fields.py +44 -0
  6. oarepo_runtime-2.0.0.dev19/oarepo_runtime/typing.py +60 -0
  7. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/.gitignore +0 -0
  8. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/LICENSE +0 -0
  9. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/README.md +0 -0
  10. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/api.py +0 -0
  11. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/cli/__init__.py +0 -0
  12. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/cli/search.py +0 -0
  13. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/config.py +0 -0
  14. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/ext.py +0 -0
  15. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/proxies.py +0 -0
  16. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/py.typed +0 -0
  17. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/records/__init__.py +0 -0
  18. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/records/drafts.py +0 -0
  19. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/records/mapping.py +0 -0
  20. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/records/pid_providers.py +0 -0
  21. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/records/systemfields/__init__.py +0 -0
  22. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/records/systemfields/mapping.py +0 -0
  23. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/records/systemfields/publication_status.py +0 -0
  24. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/resources/__init__.py +0 -0
  25. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/resources/config.py +0 -0
  26. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/services/__init__.py +0 -0
  27. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/services/config/__init__.py +0 -0
  28. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/services/config/components.py +0 -0
  29. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/services/config/link_conditions.py +0 -0
  30. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/services/config/permissions.py +0 -0
  31. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/services/facets/__init__.py +0 -0
  32. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/services/facets/params.py +0 -0
  33. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/services/generators.py +0 -0
  34. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/services/records/__init__.py +0 -0
  35. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/services/records/links.py +0 -0
  36. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/services/records/mapping.py +0 -0
  37. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/services/results.py +0 -0
  38. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/services/schema/__init__.py +0 -0
  39. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/services/schema/i18n.py +0 -0
  40. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/oarepo_runtime/services/schema/i18n_ui.py +0 -0
  41. {oarepo_runtime-2.0.0.dev18 → oarepo_runtime-2.0.0.dev19}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: oarepo-runtime
3
- Version: 2.0.0.dev18
3
+ Version: 2.0.0.dev19
4
4
  Summary: A set of runtime extensions of Invenio repository
5
5
  Project-URL: Homepage, https://github.com/oarepo/oarepo-runtime
6
6
  License-Expression: MIT
@@ -19,6 +19,6 @@ from .api import Model
19
19
  from .ext import OARepoRuntime
20
20
  from .proxies import current_runtime
21
21
 
22
- __version__ = "2.0.0dev18"
22
+ __version__ = "2.0.0dev19"
23
23
 
24
24
  __all__ = ("Model", "OARepoRuntime", "__version__", "current_runtime")
@@ -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