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
@@ -1,4 +1,23 @@
|
|
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
|
+
"""Functionality for handling multilingual UI schemas using Marshmallow.
|
11
|
+
|
12
|
+
It includes dynamic schema generation based on
|
13
|
+
the provided language and value names, as well as specialized fields for
|
14
|
+
working with multilingual data and localized user interfaces.
|
15
|
+
"""
|
16
|
+
|
17
|
+
from __future__ import annotations
|
18
|
+
|
1
19
|
from functools import lru_cache
|
20
|
+
from typing import Any
|
2
21
|
|
3
22
|
from invenio_base.utils import obj_or_import_string
|
4
23
|
from marshmallow import Schema, fields
|
@@ -6,9 +25,20 @@ from marshmallow import Schema, fields
|
|
6
25
|
|
7
26
|
@lru_cache
|
8
27
|
def get_i18n_ui_schema(
|
9
|
-
lang_name
|
10
|
-
|
28
|
+
lang_name: str,
|
29
|
+
value_name: str,
|
30
|
+
value_field: str = "marshmallow_utils.fields.SanitizedHTML",
|
31
|
+
) -> type[Schema]:
|
32
|
+
"""Dynamically creates and returns I18n Schema class.
|
33
|
+
|
34
|
+
Add custom serialization logic based on the provided `lang_name` and `value_name`.
|
35
|
+
"""
|
11
36
|
value_field_class = obj_or_import_string(value_field)
|
37
|
+
if value_field_class is None:
|
38
|
+
raise ValueError(
|
39
|
+
f"Invalid value field class provided: '{value_field}'. "
|
40
|
+
"Expected a valid import string for a Marshmallow field class."
|
41
|
+
)
|
12
42
|
return type(
|
13
43
|
f"I18nUISchema_{lang_name}_{value_name}",
|
14
44
|
(Schema,),
|
@@ -20,12 +50,13 @@ def get_i18n_ui_schema(
|
|
20
50
|
|
21
51
|
|
22
52
|
def MultilingualUIField( # noqa NOSONAR
|
23
|
-
*args,
|
24
|
-
lang_name="lang",
|
25
|
-
value_name="value",
|
26
|
-
value_field="marshmallow_utils.fields.SanitizedHTML",
|
27
|
-
**kwargs,
|
53
|
+
*args: Any,
|
54
|
+
lang_name: str = "lang",
|
55
|
+
value_name: str = "value",
|
56
|
+
value_field: str = "marshmallow_utils.fields.SanitizedHTML",
|
57
|
+
**kwargs: Any,
|
28
58
|
):
|
59
|
+
_ = args
|
29
60
|
return fields.List(
|
30
61
|
fields.Nested(get_i18n_ui_schema(lang_name, value_name, value_field)),
|
31
62
|
**kwargs,
|
@@ -33,12 +64,12 @@ def MultilingualUIField( # noqa NOSONAR
|
|
33
64
|
|
34
65
|
|
35
66
|
def I18nStrUIField( # noqa NOSONAR
|
36
|
-
*args,
|
37
|
-
lang_name="lang",
|
38
|
-
value_name="value",
|
39
|
-
value_field="marshmallow_utils.fields.SanitizedHTML",
|
40
|
-
**kwargs,
|
41
|
-
):
|
67
|
+
*args: Any,
|
68
|
+
lang_name: str = "lang",
|
69
|
+
value_name: str = "value",
|
70
|
+
value_field: str = "marshmallow_utils.fields.SanitizedHTML",
|
71
|
+
**kwargs: Any,
|
72
|
+
) -> fields.Field:
|
42
73
|
return fields.Nested(
|
43
74
|
get_i18n_ui_schema(lang_name, value_name, value_field),
|
44
75
|
*args,
|
@@ -47,16 +78,22 @@ def I18nStrUIField( # noqa NOSONAR
|
|
47
78
|
|
48
79
|
|
49
80
|
@lru_cache
|
50
|
-
def get_i18n_localized_ui_schema(lang_name, value_name):
|
81
|
+
def get_i18n_localized_ui_schema(lang_name: str, value_name: str) -> type[Schema]:
|
82
|
+
"""Dynamically creates and returns Localized I18n Schema class.
|
83
|
+
|
84
|
+
Add custom serialization logic based on the provided `lang_name` and `value_name`.
|
85
|
+
"""
|
86
|
+
|
51
87
|
class I18nLocalizedUISchema(Schema):
|
52
|
-
def _serialize(self,
|
53
|
-
|
88
|
+
def _serialize(self, obj: Any, *, many: bool | None = None) -> Any:
|
89
|
+
_ = many
|
90
|
+
if not obj:
|
54
91
|
return None
|
55
92
|
language = self.context["locale"].language
|
56
|
-
for v in
|
93
|
+
for v in obj:
|
57
94
|
if language == v[lang_name]:
|
58
95
|
return v[value_name]
|
59
|
-
return next(iter(
|
96
|
+
return next(iter(obj))[value_name]
|
60
97
|
|
61
98
|
# inherit to get a nice name for debugging
|
62
99
|
return type(
|
@@ -67,16 +104,16 @@ def get_i18n_localized_ui_schema(lang_name, value_name):
|
|
67
104
|
|
68
105
|
|
69
106
|
def MultilingualLocalizedUIField( # noqa NOSONAR
|
70
|
-
*args, lang_name="lang", value_name="value", **kwargs
|
71
|
-
):
|
72
|
-
return fields.Nested(get_i18n_localized_ui_schema(lang_name, value_name), **kwargs)
|
107
|
+
*args: Any, lang_name: str = "lang", value_name: str = "value", **kwargs: Any
|
108
|
+
) -> fields.Field:
|
109
|
+
return fields.Nested(get_i18n_localized_ui_schema(lang_name, value_name), *args, **kwargs)
|
73
110
|
|
74
111
|
|
75
112
|
def I18nStrLocalizedUIField( # noqa NOSONAR
|
76
|
-
*args, lang_name="lang", value_name="value", **kwargs
|
77
|
-
):
|
113
|
+
*args: Any, lang_name: str = "lang", value_name: str = "value", **kwargs: Any
|
114
|
+
) -> fields.Field:
|
115
|
+
_ = args
|
78
116
|
return fields.Nested(
|
79
117
|
get_i18n_ui_schema(lang_name, value_name),
|
80
|
-
*args,
|
81
118
|
**kwargs,
|
82
119
|
)
|
@@ -1,29 +1,17 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: oarepo-runtime
|
3
|
-
Version:
|
3
|
+
Version: 2.0.0.dev3
|
4
4
|
Summary: A set of runtime extensions of Invenio repository
|
5
|
-
|
5
|
+
License-Expression: MIT
|
6
6
|
License-File: LICENSE
|
7
|
-
Requires-
|
8
|
-
Requires-Dist: langcodes
|
9
|
-
Requires-Dist:
|
10
|
-
Requires-Dist: openpyxl
|
11
|
-
Requires-Dist: flask-babelex
|
12
|
-
Requires-Dist: deepmerge
|
13
|
-
Requires-Dist: tqdm
|
14
|
-
Requires-Dist: deprecated
|
15
|
-
Requires-Dist: idutils
|
7
|
+
Requires-Python: <3.14,>=3.13
|
8
|
+
Requires-Dist: langcodes>=3.5.0
|
9
|
+
Requires-Dist: oarepo[rdm,tests]<14,>=13
|
16
10
|
Provides-Extra: dev
|
17
|
-
Requires-Dist: pytest>=7.1.2; extra ==
|
18
|
-
Requires-Dist: black; extra == "dev"
|
19
|
-
Requires-Dist: isort; extra == "dev"
|
20
|
-
Requires-Dist: autoflake; extra == "dev"
|
21
|
-
Requires-Dist: oarepo-tools; extra == "dev"
|
11
|
+
Requires-Dist: pytest>=7.1.2; extra == 'dev'
|
22
12
|
Provides-Extra: tests
|
23
|
-
Requires-Dist: pytest>=7.1.2; extra ==
|
24
|
-
|
25
|
-
Requires-Dist: psutil; extra == "tests"
|
26
|
-
Dynamic: license-file
|
13
|
+
Requires-Dist: pytest>=7.1.2; extra == 'tests'
|
14
|
+
Description-Content-Type: text/markdown
|
27
15
|
|
28
16
|
# OARepo runtime
|
29
17
|
|
@@ -172,4 +160,4 @@ Will print/write to file a json with the following format:
|
|
172
160
|
```
|
173
161
|
```json
|
174
162
|
|
175
|
-
```
|
163
|
+
```
|
@@ -0,0 +1,30 @@
|
|
1
|
+
oarepo_runtime/__init__.py,sha256=hLYRfE2IAzqCkcxlBoCopCZceljM89PTrpiN7k5FHv8,685
|
2
|
+
oarepo_runtime/api.py,sha256=h3iwvDtL1AFYOQqKd6HJj1cnbxM_gy1IWt4gFcSzzSc,3826
|
3
|
+
oarepo_runtime/config.py,sha256=auPBzCMXIcYdA1Tee5srMtfu0D5lDd38sn4BO5wGVJ4,2540
|
4
|
+
oarepo_runtime/ext.py,sha256=AMb5pMnCSbqIpPyP99YUKlf9vopz_b2ZW-RnvfsEVlk,3254
|
5
|
+
oarepo_runtime/proxies.py,sha256=PXaRiBh5qs5-h8M81cJOgtqypFQcYUSjiSn2TLSujRw,648
|
6
|
+
oarepo_runtime/cli/__init__.py,sha256=iPs1a4blP7750rwEXobzK3YHgsfGxoVTZxwWMslAlTY,350
|
7
|
+
oarepo_runtime/cli/search.py,sha256=yqYHZauXsDBPpN4odYsPOWNQ9xWmAofQ407EAyqx6CY,1137
|
8
|
+
oarepo_runtime/records/__init__.py,sha256=AbWzmVCY7MhrpdEeI0e3lKzeugPMUSo8T08-NBVeig4,339
|
9
|
+
oarepo_runtime/records/drafts.py,sha256=CS-dUkrylNwscgBGfDyhwGBRCzwsyT6AA3Mhu40ShbY,1607
|
10
|
+
oarepo_runtime/records/mapping.py,sha256=SJbSzerT1645a93-3-Fgz_i3anzFNlrZqbjjwW2ctKs,2660
|
11
|
+
oarepo_runtime/records/pid_providers.py,sha256=pVXVeYmAsXy-IEdM2zHZ7UWkAnzXg1gtssfLc9QZbPA,1717
|
12
|
+
oarepo_runtime/records/systemfields/__init__.py,sha256=g-u408qyNnsbUTpDtVVwlcyiJaO68GTjDN0W9rXs9pk,524
|
13
|
+
oarepo_runtime/records/systemfields/mapping.py,sha256=66OQavKewJEUMkghymOxvskIO0LUSP2E-MbHryeT5Nk,1968
|
14
|
+
oarepo_runtime/records/systemfields/publication_status.py,sha256=vYIwueI37Auh84IptSxeF9KYC32EGmBe3-Rk1DWXMF8,1957
|
15
|
+
oarepo_runtime/services/__init__.py,sha256=OGtBgEeaDTyk2RPDNXuKbU9_7egFBZr42SM0gN5FrF4,341
|
16
|
+
oarepo_runtime/services/results.py,sha256=fk-Enx_LwZLbw81yZ7CXVTku86vd3_fjprnb8l5sFHk,6657
|
17
|
+
oarepo_runtime/services/config/__init__.py,sha256=SX1kfIGk8HkohdLQrNpRQUTltksEyDcCa-kFXxrX4e8,711
|
18
|
+
oarepo_runtime/services/config/link_conditions.py,sha256=raqf4yaBNLqNYgBxVNblo8MRJneVIFkwVNW7IW3AVYI,4309
|
19
|
+
oarepo_runtime/services/config/permissions.py,sha256=x5k61LGnpXyJfXVoCTq2tTVTtPckmBcBtcBJx4UN9EA,3056
|
20
|
+
oarepo_runtime/services/records/__init__.py,sha256=c0n4vcMcJhSUWsKz0iyV4TTlGG8oLlJp0YEN0QGCZ8U,428
|
21
|
+
oarepo_runtime/services/records/links.py,sha256=lqvnXabquL4DqWV93cdUYNUVYHx7T5Q0EXXuWAHM33A,1078
|
22
|
+
oarepo_runtime/services/records/mapping.py,sha256=y3oeToKEnaRYpMV3q2-2cXNzyzyL3XXGvY26BifybpE,1332
|
23
|
+
oarepo_runtime/services/schema/__init__.py,sha256=jgAPI_uKC6Ug4KQWnwQVg3-aNaw-eHja323AUFo5ELo,351
|
24
|
+
oarepo_runtime/services/schema/i18n.py,sha256=9D1zOQaPKAnYzejB0vO-m2BJYnam0N0Lrq4jID7twfE,3174
|
25
|
+
oarepo_runtime/services/schema/i18n_ui.py,sha256=DbusphhGDeaobTt4nuwNgKZ6Houlu4Sv3SuMGkdjRRY,3582
|
26
|
+
oarepo_runtime-2.0.0.dev3.dist-info/METADATA,sha256=nLtfS-x8LURACObTJYTyGeXIzHMQ9jtSzfg_l145cHo,4430
|
27
|
+
oarepo_runtime-2.0.0.dev3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
28
|
+
oarepo_runtime-2.0.0.dev3.dist-info/entry_points.txt,sha256=7HqK5jumIgDVJa7ifjPKizginfIm5_R_qUVKPf_Yq-c,145
|
29
|
+
oarepo_runtime-2.0.0.dev3.dist-info/licenses/LICENSE,sha256=h2uWz0OaB3EN-J1ImdGJZzc7yvfQjvHVYdUhQ-H7ypY,1064
|
30
|
+
oarepo_runtime-2.0.0.dev3.dist-info/RECORD,,
|
oarepo_runtime/cli/assets.py
DELETED
@@ -1,145 +0,0 @@
|
|
1
|
-
import json
|
2
|
-
import os
|
3
|
-
import re
|
4
|
-
from pathlib import Path
|
5
|
-
|
6
|
-
import click
|
7
|
-
from flask import current_app
|
8
|
-
from flask.cli import with_appcontext
|
9
|
-
from flask_webpackext import current_webpack
|
10
|
-
from importlib_metadata import entry_points
|
11
|
-
|
12
|
-
from .base import oarepo
|
13
|
-
|
14
|
-
|
15
|
-
@oarepo.group()
|
16
|
-
def assets():
|
17
|
-
"OARepo asset addons"
|
18
|
-
|
19
|
-
|
20
|
-
@assets.command()
|
21
|
-
@click.argument("output_file")
|
22
|
-
@click.option("--repository-dir")
|
23
|
-
@click.option("--assets-dir", default=".assets")
|
24
|
-
@with_appcontext
|
25
|
-
def collect(output_file, repository_dir, assets_dir):
|
26
|
-
aliases, asset_dirs, generated_paths = enumerate_assets()
|
27
|
-
|
28
|
-
app_and_blueprints = [current_app] + list(current_app.blueprints.values())
|
29
|
-
|
30
|
-
static_deps = []
|
31
|
-
instance_path = current_app.instance_path
|
32
|
-
if instance_path[-1] != "/":
|
33
|
-
instance_path += "/"
|
34
|
-
|
35
|
-
for bp in app_and_blueprints:
|
36
|
-
if (
|
37
|
-
bp.has_static_folder
|
38
|
-
and os.path.isdir(bp.static_folder)
|
39
|
-
and not bp.static_folder.startswith(instance_path)
|
40
|
-
):
|
41
|
-
static_deps.append(bp.static_folder)
|
42
|
-
|
43
|
-
root_aliases = {}
|
44
|
-
asset_paths = [Path(x) for x in asset_dirs]
|
45
|
-
for alias, path in aliases.items():
|
46
|
-
for pth in asset_paths:
|
47
|
-
possible_path = pth / path
|
48
|
-
if possible_path.exists():
|
49
|
-
try:
|
50
|
-
relative_path = str(
|
51
|
-
possible_path.relative_to(repository_dir or os.getcwd())
|
52
|
-
)
|
53
|
-
root_aliases[alias] = "./" + relative_path
|
54
|
-
except ValueError:
|
55
|
-
root_aliases[alias] = str(Path(assets_dir) / path)
|
56
|
-
|
57
|
-
with open(output_file, "w") as f:
|
58
|
-
json.dump(
|
59
|
-
{
|
60
|
-
"assets": asset_dirs,
|
61
|
-
"static": static_deps,
|
62
|
-
"@aliases": aliases,
|
63
|
-
"@root_aliases": root_aliases,
|
64
|
-
"generated": generated_paths,
|
65
|
-
},
|
66
|
-
f,
|
67
|
-
indent=4,
|
68
|
-
ensure_ascii=False,
|
69
|
-
)
|
70
|
-
|
71
|
-
|
72
|
-
def enumerate_assets():
|
73
|
-
asset_dirs = []
|
74
|
-
generated_paths = []
|
75
|
-
aliases = {}
|
76
|
-
themes = current_app.config["APP_THEME"] or ["semantic-ui"]
|
77
|
-
project = current_webpack.project
|
78
|
-
if hasattr(project, 'generated_paths'):
|
79
|
-
generated_paths += project.generated_paths
|
80
|
-
|
81
|
-
for ep in entry_points(group="invenio_assets.webpack"):
|
82
|
-
webpack = ep.load()
|
83
|
-
for wp_theme_name, wp_theme in webpack.themes.items():
|
84
|
-
if wp_theme_name in themes:
|
85
|
-
asset_dirs.append(wp_theme.path)
|
86
|
-
if hasattr(wp_theme, "generated_paths"):
|
87
|
-
generated_paths += list(set(wp_theme.generated_paths) - set(generated_paths))
|
88
|
-
aliases.update(wp_theme.aliases)
|
89
|
-
return aliases, asset_dirs, generated_paths
|
90
|
-
|
91
|
-
|
92
|
-
COMPONENT_LIST_RE = re.compile(
|
93
|
-
r"""
|
94
|
-
^
|
95
|
-
\s*
|
96
|
-
& # start of import statement & { import "blah"; }
|
97
|
-
\s*
|
98
|
-
{
|
99
|
-
\s*
|
100
|
-
(
|
101
|
-
@import\s+["'](.*?)["']
|
102
|
-
\s*
|
103
|
-
;
|
104
|
-
)+
|
105
|
-
\s*
|
106
|
-
}""",
|
107
|
-
re.MULTILINE | re.DOTALL | re.VERBOSE,
|
108
|
-
)
|
109
|
-
|
110
|
-
COMPONENT_RE = re.compile(
|
111
|
-
r"""
|
112
|
-
\s*
|
113
|
-
@import\s+["'](.*?)["']
|
114
|
-
\s*
|
115
|
-
;
|
116
|
-
\s*
|
117
|
-
""",
|
118
|
-
re.MULTILINE | re.DOTALL | re.VERBOSE,
|
119
|
-
)
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
@assets.command(name="less-components")
|
124
|
-
@click.argument("output_file", default="-")
|
125
|
-
@with_appcontext
|
126
|
-
def less_components(output_file):
|
127
|
-
aliases, asset_dirs, _ = enumerate_assets()
|
128
|
-
asset_dirs = [Path(x) for x in asset_dirs]
|
129
|
-
less_component_files = []
|
130
|
-
for asset_dir in asset_dirs:
|
131
|
-
less_dir = asset_dir / "less"
|
132
|
-
if less_dir.exists():
|
133
|
-
for f in less_dir.glob("**/custom-components.less"):
|
134
|
-
less_component_files.append(f)
|
135
|
-
components = set()
|
136
|
-
for cmp_file in less_component_files:
|
137
|
-
for component_list in COMPONENT_LIST_RE.findall(cmp_file.read_text()):
|
138
|
-
for s in COMPONENT_RE.findall(component_list[0]):
|
139
|
-
components.add(Path(s).stem)
|
140
|
-
data = {"components": list(sorted(components))}
|
141
|
-
if output_file == "-":
|
142
|
-
print(json.dumps(data, indent=4, ensure_ascii=False))
|
143
|
-
else:
|
144
|
-
with open(output_file, "w") as f:
|
145
|
-
json.dump(data, f, indent=4, ensure_ascii=False)
|
oarepo_runtime/cli/base.py
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
import json
|
2
|
-
|
3
|
-
import click
|
4
|
-
import importlib_metadata
|
5
|
-
|
6
|
-
|
7
|
-
@click.group()
|
8
|
-
def oarepo():
|
9
|
-
"""OARepo commands."""
|
10
|
-
|
11
|
-
|
12
|
-
def as_command(group, name, *args):
|
13
|
-
args = [group.command(name=name), *args]
|
14
|
-
actual = args[-1]
|
15
|
-
for arg in reversed(args[:-1]):
|
16
|
-
actual = arg(actual)
|
17
|
-
return actual
|
18
|
-
|
19
|
-
|
20
|
-
@oarepo.command(name="version")
|
21
|
-
def get_version():
|
22
|
-
versions = {}
|
23
|
-
for distro in importlib_metadata.distributions():
|
24
|
-
versions[distro.metadata["Name"]] = distro.version
|
25
|
-
print(json.dumps(versions, ensure_ascii=False, indent=4))
|
oarepo_runtime/cli/cf.py
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
from flask.cli import with_appcontext
|
2
|
-
|
3
|
-
from oarepo_runtime.cli import oarepo
|
4
|
-
from oarepo_runtime.services.custom_fields.mappings import prepare_cf_indices
|
5
|
-
|
6
|
-
|
7
|
-
@oarepo.group()
|
8
|
-
def cf():
|
9
|
-
"""Custom fields commands."""
|
10
|
-
|
11
|
-
|
12
|
-
@cf.command(name="init", help="Prepare custom fields in indices")
|
13
|
-
@with_appcontext
|
14
|
-
def init():
|
15
|
-
prepare_cf_indices()
|
oarepo_runtime/cli/check.py
DELETED
@@ -1,167 +0,0 @@
|
|
1
|
-
import json
|
2
|
-
import random
|
3
|
-
import traceback
|
4
|
-
|
5
|
-
import click
|
6
|
-
import kombu.exceptions
|
7
|
-
import opensearchpy
|
8
|
-
import redis
|
9
|
-
from flask import current_app
|
10
|
-
from flask.cli import with_appcontext
|
11
|
-
from invenio_db import db
|
12
|
-
from invenio_files_rest.models import Location
|
13
|
-
from invenio_pidstore.models import PersistentIdentifier
|
14
|
-
from invenio_records_resources.proxies import current_service_registry
|
15
|
-
from opensearchpy import TransportError
|
16
|
-
|
17
|
-
from .base import oarepo
|
18
|
-
|
19
|
-
|
20
|
-
@oarepo.command(name="check")
|
21
|
-
@click.argument("output_file", default="-")
|
22
|
-
@with_appcontext
|
23
|
-
def check(output_file):
|
24
|
-
status = {}
|
25
|
-
status["db"] = check_database()
|
26
|
-
status["opensearch"] = check_opensearch()
|
27
|
-
status["files"] = check_files()
|
28
|
-
status["mq"] = check_message_queue()
|
29
|
-
status["cache"] = check_cache()
|
30
|
-
if output_file == "-":
|
31
|
-
print(
|
32
|
-
json.dumps(status, indent=4, ensure_ascii=False, default=lambda x: str(x))
|
33
|
-
)
|
34
|
-
else:
|
35
|
-
with open(output_file, "w") as f:
|
36
|
-
json.dump(status, f, ensure_ascii=False, default=lambda x: str(x))
|
37
|
-
|
38
|
-
|
39
|
-
def check_database():
|
40
|
-
if not has_database_connection():
|
41
|
-
return "connection_error"
|
42
|
-
try:
|
43
|
-
db.session.begin()
|
44
|
-
try:
|
45
|
-
PersistentIdentifier.query.all()[:1]
|
46
|
-
except:
|
47
|
-
return "not_initialized"
|
48
|
-
alembic = current_app.extensions["invenio-db"].alembic
|
49
|
-
context = alembic.migration_context
|
50
|
-
db_heads = set(context.get_current_heads())
|
51
|
-
source_heads = [x.revision for x in alembic.current()]
|
52
|
-
for h in source_heads:
|
53
|
-
if h not in db_heads:
|
54
|
-
return "migration_pending"
|
55
|
-
return "ok"
|
56
|
-
finally:
|
57
|
-
db.session.rollback()
|
58
|
-
|
59
|
-
|
60
|
-
def has_database_connection():
|
61
|
-
try:
|
62
|
-
db.session.begin()
|
63
|
-
db.session.execute("SELECT 1")
|
64
|
-
return True
|
65
|
-
except:
|
66
|
-
return False
|
67
|
-
finally:
|
68
|
-
db.session.rollback()
|
69
|
-
|
70
|
-
|
71
|
-
def check_opensearch():
|
72
|
-
services = current_service_registry._services.keys()
|
73
|
-
checked_indexers = set()
|
74
|
-
for service_id in services:
|
75
|
-
service = current_service_registry.get(service_id)
|
76
|
-
record_class = getattr(service.config, "record_cls", None)
|
77
|
-
if not record_class: # files??
|
78
|
-
continue
|
79
|
-
indexer = getattr(service, "indexer", None)
|
80
|
-
if not indexer:
|
81
|
-
continue
|
82
|
-
if id(indexer) not in checked_indexers:
|
83
|
-
checked_indexers.add(id(indexer))
|
84
|
-
try:
|
85
|
-
indexer.client.indices.exists("test")
|
86
|
-
except opensearchpy.exceptions.ConnectionError:
|
87
|
-
return "connection_error"
|
88
|
-
|
89
|
-
|
90
|
-
try:
|
91
|
-
index = indexer._prepare_index(indexer.record_to_index(record_class))
|
92
|
-
except AttributeError:
|
93
|
-
print(f"Warning: can not get index name for record class {record_class}")
|
94
|
-
continue
|
95
|
-
|
96
|
-
try:
|
97
|
-
service.indexer.client.indices.get(index=index)
|
98
|
-
except TransportError:
|
99
|
-
return f"index_missing:{index}"
|
100
|
-
return "ok"
|
101
|
-
|
102
|
-
|
103
|
-
def check_files():
|
104
|
-
if not has_database_connection():
|
105
|
-
return "db_connection_error"
|
106
|
-
|
107
|
-
try:
|
108
|
-
db.session.begin()
|
109
|
-
# check that there is the default location and that is readable
|
110
|
-
default_location = Location.get_default()
|
111
|
-
if not default_location:
|
112
|
-
return "default_location_missing"
|
113
|
-
except: # NOSONAR - we are not interested what the exception is
|
114
|
-
return "db_error"
|
115
|
-
finally:
|
116
|
-
db.session.rollback()
|
117
|
-
|
118
|
-
try:
|
119
|
-
import s3fs
|
120
|
-
except ImportError:
|
121
|
-
return f"s3_support_not_installed"
|
122
|
-
|
123
|
-
try:
|
124
|
-
info = current_app.extensions["invenio-s3"].init_s3fs_info
|
125
|
-
fs = s3fs.S3FileSystem(default_block_size=4096, **info)
|
126
|
-
fs.ls(default_location.uri.replace("s3://", ""))
|
127
|
-
except: # NOSONAR - we are not interested what the exception is
|
128
|
-
return f"bucket_does_not_exist:{default_location.uri}"
|
129
|
-
|
130
|
-
return "ok"
|
131
|
-
|
132
|
-
|
133
|
-
def check_message_queue():
|
134
|
-
try:
|
135
|
-
from celery import current_app
|
136
|
-
|
137
|
-
current_app.control.inspect().active()
|
138
|
-
return "ok"
|
139
|
-
except kombu.exceptions.OperationalError as e:
|
140
|
-
if isinstance(e.__cause__, ConnectionRefusedError):
|
141
|
-
return "connection_error"
|
142
|
-
return "mq_error"
|
143
|
-
except: # NOSONAR - we are not interested what the exception is
|
144
|
-
return "mq_error"
|
145
|
-
|
146
|
-
|
147
|
-
def check_cache():
|
148
|
-
try:
|
149
|
-
from invenio_cache.proxies import current_cache
|
150
|
-
|
151
|
-
rnd = str(
|
152
|
-
random.randint(0, 10000) # NOSONAR - this is not a cryptographic random
|
153
|
-
)
|
154
|
-
# it is here just to make sure that what we put to the cache is what we get back
|
155
|
-
|
156
|
-
current_cache.set("oarepo_check", rnd)
|
157
|
-
if current_cache.get("oarepo_check") == rnd:
|
158
|
-
return "ok"
|
159
|
-
else:
|
160
|
-
return "cache_error"
|
161
|
-
except redis.exceptions.ConnectionError as e:
|
162
|
-
if isinstance(e.__cause__, ConnectionRefusedError):
|
163
|
-
return "connection_error"
|
164
|
-
return "cache_exception"
|
165
|
-
except: # NOSONAR - we are not interested what the exception is
|
166
|
-
traceback.print_exc()
|
167
|
-
return "cache_exception"
|
@@ -1,51 +0,0 @@
|
|
1
|
-
import json
|
2
|
-
from collections.abc import Mapping, Sequence, Set
|
3
|
-
|
4
|
-
import click
|
5
|
-
from flask import current_app
|
6
|
-
from flask.cli import with_appcontext
|
7
|
-
from werkzeug.local import LocalProxy
|
8
|
-
|
9
|
-
from .base import oarepo
|
10
|
-
|
11
|
-
def remove_lazy_objects(obj):
|
12
|
-
if isinstance(obj, Sequence):
|
13
|
-
if isinstance(obj, list):
|
14
|
-
return [remove_lazy_objects(item) for item in obj if not isinstance(item, LocalProxy)]
|
15
|
-
elif isinstance(obj, tuple):
|
16
|
-
return tuple(remove_lazy_objects(item) for item in obj if not isinstance(item, LocalProxy))
|
17
|
-
elif not isinstance(obj, LocalProxy):
|
18
|
-
return obj # strings, bytes, bytesarray etc.
|
19
|
-
elif isinstance(obj, Set):
|
20
|
-
if isinstance(obj, frozenset):
|
21
|
-
return frozenset(remove_lazy_objects(item) for item in obj if not isinstance(item, LocalProxy))
|
22
|
-
return {remove_lazy_objects(item) for item in obj if not isinstance(item, LocalProxy)}
|
23
|
-
elif isinstance(obj, Mapping):
|
24
|
-
return {k: remove_lazy_objects(v) for k, v in obj.items() if not isinstance(v, LocalProxy)}
|
25
|
-
elif not isinstance(obj, LocalProxy):
|
26
|
-
return obj # everything else that is not localproxy
|
27
|
-
|
28
|
-
@oarepo.command(name="configuration")
|
29
|
-
@click.argument("output_file", default="-")
|
30
|
-
@with_appcontext
|
31
|
-
def configuration_command(output_file):
|
32
|
-
configuration = remove_lazy_objects(current_app.config)
|
33
|
-
|
34
|
-
try:
|
35
|
-
invenio_db = current_app.extensions["invenio-db"]
|
36
|
-
alembic_config = invenio_db.alembic.config
|
37
|
-
configuration["ALEMBIC_LOCATIONS"] = alembic_config.get_main_option(
|
38
|
-
"version_locations"
|
39
|
-
).split(",")
|
40
|
-
except Exception as e:
|
41
|
-
configuration["ALEMBIC_LOCATIONS_ERROR"] = str(e)
|
42
|
-
|
43
|
-
if output_file == "-":
|
44
|
-
print(
|
45
|
-
json.dumps(
|
46
|
-
configuration, skipkeys=True, indent=4, ensure_ascii=False, default=lambda x: str(x)
|
47
|
-
)
|
48
|
-
)
|
49
|
-
else:
|
50
|
-
with open(output_file, "w") as f:
|
51
|
-
json.dump(configuration, f,skipkeys=True, ensure_ascii=False, default=lambda x: str(x))
|