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.
Files changed (171) hide show
  1. oarepo_runtime/__init__.py +24 -0
  2. oarepo_runtime/api.py +111 -0
  3. oarepo_runtime/cli/__init__.py +10 -21
  4. oarepo_runtime/cli/search.py +34 -0
  5. oarepo_runtime/config.py +86 -13
  6. oarepo_runtime/ext.py +64 -82
  7. oarepo_runtime/proxies.py +21 -5
  8. oarepo_runtime/records/__init__.py +11 -50
  9. oarepo_runtime/records/drafts.py +24 -18
  10. oarepo_runtime/records/mapping.py +84 -0
  11. oarepo_runtime/records/pid_providers.py +43 -7
  12. oarepo_runtime/records/systemfields/__init__.py +15 -33
  13. oarepo_runtime/records/systemfields/mapping.py +41 -24
  14. oarepo_runtime/records/systemfields/publication_status.py +59 -0
  15. oarepo_runtime/services/__init__.py +12 -0
  16. oarepo_runtime/services/config/__init__.py +15 -21
  17. oarepo_runtime/services/config/link_conditions.py +69 -75
  18. oarepo_runtime/services/config/permissions.py +62 -0
  19. oarepo_runtime/services/records/__init__.py +14 -1
  20. oarepo_runtime/services/records/links.py +21 -11
  21. oarepo_runtime/services/records/mapping.py +42 -0
  22. oarepo_runtime/services/results.py +98 -109
  23. oarepo_runtime/services/schema/__init__.py +12 -44
  24. oarepo_runtime/services/schema/i18n.py +47 -22
  25. oarepo_runtime/services/schema/i18n_ui.py +61 -24
  26. {oarepo_runtime-1.10.2.dist-info → oarepo_runtime-2.0.0.dev3.dist-info}/METADATA +9 -21
  27. oarepo_runtime-2.0.0.dev3.dist-info/RECORD +30 -0
  28. {oarepo_runtime-1.10.2.dist-info → oarepo_runtime-2.0.0.dev3.dist-info}/WHEEL +1 -2
  29. oarepo_runtime-2.0.0.dev3.dist-info/entry_points.txt +5 -0
  30. oarepo_runtime/cli/assets.py +0 -145
  31. oarepo_runtime/cli/base.py +0 -25
  32. oarepo_runtime/cli/cf.py +0 -15
  33. oarepo_runtime/cli/check.py +0 -167
  34. oarepo_runtime/cli/configuration.py +0 -51
  35. oarepo_runtime/cli/fixtures.py +0 -167
  36. oarepo_runtime/cli/index.py +0 -272
  37. oarepo_runtime/cli/permissions/__init__.py +0 -6
  38. oarepo_runtime/cli/permissions/base.py +0 -26
  39. oarepo_runtime/cli/permissions/evaluate.py +0 -63
  40. oarepo_runtime/cli/permissions/list.py +0 -239
  41. oarepo_runtime/cli/permissions/search.py +0 -121
  42. oarepo_runtime/cli/validate.py +0 -150
  43. oarepo_runtime/datastreams/__init__.py +0 -38
  44. oarepo_runtime/datastreams/asynchronous.py +0 -247
  45. oarepo_runtime/datastreams/catalogue.py +0 -150
  46. oarepo_runtime/datastreams/datastreams.py +0 -152
  47. oarepo_runtime/datastreams/errors.py +0 -54
  48. oarepo_runtime/datastreams/ext.py +0 -41
  49. oarepo_runtime/datastreams/fixtures.py +0 -265
  50. oarepo_runtime/datastreams/json.py +0 -4
  51. oarepo_runtime/datastreams/readers/__init__.py +0 -39
  52. oarepo_runtime/datastreams/readers/attachments.py +0 -51
  53. oarepo_runtime/datastreams/readers/excel.py +0 -123
  54. oarepo_runtime/datastreams/readers/json.py +0 -27
  55. oarepo_runtime/datastreams/readers/service.py +0 -54
  56. oarepo_runtime/datastreams/readers/yaml.py +0 -14
  57. oarepo_runtime/datastreams/semi_asynchronous.py +0 -91
  58. oarepo_runtime/datastreams/synchronous.py +0 -70
  59. oarepo_runtime/datastreams/transformers.py +0 -18
  60. oarepo_runtime/datastreams/types.py +0 -323
  61. oarepo_runtime/datastreams/utils.py +0 -131
  62. oarepo_runtime/datastreams/writers/__init__.py +0 -21
  63. oarepo_runtime/datastreams/writers/attachments_file.py +0 -92
  64. oarepo_runtime/datastreams/writers/attachments_service.py +0 -118
  65. oarepo_runtime/datastreams/writers/publish.py +0 -70
  66. oarepo_runtime/datastreams/writers/service.py +0 -175
  67. oarepo_runtime/datastreams/writers/utils.py +0 -30
  68. oarepo_runtime/datastreams/writers/validation_errors.py +0 -20
  69. oarepo_runtime/datastreams/writers/yaml.py +0 -56
  70. oarepo_runtime/ext_config.py +0 -67
  71. oarepo_runtime/i18n/__init__.py +0 -3
  72. oarepo_runtime/info/__init__.py +0 -0
  73. oarepo_runtime/info/check.py +0 -95
  74. oarepo_runtime/info/permissions/__init__.py +0 -0
  75. oarepo_runtime/info/permissions/debug.py +0 -191
  76. oarepo_runtime/info/views.py +0 -586
  77. oarepo_runtime/profile.py +0 -60
  78. oarepo_runtime/records/dumpers/__init__.py +0 -8
  79. oarepo_runtime/records/dumpers/edtf_interval.py +0 -38
  80. oarepo_runtime/records/dumpers/multilingual_dumper.py +0 -34
  81. oarepo_runtime/records/entity_resolvers/__init__.py +0 -13
  82. oarepo_runtime/records/entity_resolvers/proxies.py +0 -57
  83. oarepo_runtime/records/mappings/__init__.py +0 -0
  84. oarepo_runtime/records/mappings/rdm_parent_mapping.json +0 -483
  85. oarepo_runtime/records/owners/__init__.py +0 -3
  86. oarepo_runtime/records/owners/registry.py +0 -22
  87. oarepo_runtime/records/relations/__init__.py +0 -22
  88. oarepo_runtime/records/relations/base.py +0 -296
  89. oarepo_runtime/records/relations/internal.py +0 -46
  90. oarepo_runtime/records/relations/lookup.py +0 -28
  91. oarepo_runtime/records/relations/pid_relation.py +0 -102
  92. oarepo_runtime/records/systemfields/featured_file.py +0 -45
  93. oarepo_runtime/records/systemfields/has_draftcheck.py +0 -47
  94. oarepo_runtime/records/systemfields/icu.py +0 -371
  95. oarepo_runtime/records/systemfields/owner.py +0 -115
  96. oarepo_runtime/records/systemfields/record_status.py +0 -35
  97. oarepo_runtime/records/systemfields/selectors.py +0 -98
  98. oarepo_runtime/records/systemfields/synthetic.py +0 -130
  99. oarepo_runtime/resources/__init__.py +0 -4
  100. oarepo_runtime/resources/config.py +0 -12
  101. oarepo_runtime/resources/file_resource.py +0 -15
  102. oarepo_runtime/resources/json_serializer.py +0 -27
  103. oarepo_runtime/resources/localized_ui_json_serializer.py +0 -54
  104. oarepo_runtime/resources/resource.py +0 -53
  105. oarepo_runtime/resources/responses.py +0 -20
  106. oarepo_runtime/services/components.py +0 -429
  107. oarepo_runtime/services/config/draft_link.py +0 -23
  108. oarepo_runtime/services/config/permissions_presets.py +0 -174
  109. oarepo_runtime/services/config/service.py +0 -117
  110. oarepo_runtime/services/custom_fields/__init__.py +0 -80
  111. oarepo_runtime/services/custom_fields/mappings.py +0 -188
  112. oarepo_runtime/services/entity/__init__.py +0 -0
  113. oarepo_runtime/services/entity/config.py +0 -14
  114. oarepo_runtime/services/entity/schema.py +0 -9
  115. oarepo_runtime/services/entity/service.py +0 -48
  116. oarepo_runtime/services/expansions/__init__.py +0 -0
  117. oarepo_runtime/services/expansions/expandable_fields.py +0 -21
  118. oarepo_runtime/services/expansions/service.py +0 -4
  119. oarepo_runtime/services/facets/__init__.py +0 -33
  120. oarepo_runtime/services/facets/base.py +0 -12
  121. oarepo_runtime/services/facets/date.py +0 -72
  122. oarepo_runtime/services/facets/enum.py +0 -11
  123. oarepo_runtime/services/facets/facet_groups_names.py +0 -17
  124. oarepo_runtime/services/facets/max_facet.py +0 -13
  125. oarepo_runtime/services/facets/multilingual_facet.py +0 -33
  126. oarepo_runtime/services/facets/nested_facet.py +0 -32
  127. oarepo_runtime/services/facets/params.py +0 -192
  128. oarepo_runtime/services/facets/year_histogram.py +0 -200
  129. oarepo_runtime/services/files/__init__.py +0 -8
  130. oarepo_runtime/services/files/components.py +0 -62
  131. oarepo_runtime/services/files/service.py +0 -16
  132. oarepo_runtime/services/generators.py +0 -10
  133. oarepo_runtime/services/permissions/__init__.py +0 -3
  134. oarepo_runtime/services/permissions/generators.py +0 -103
  135. oarepo_runtime/services/relations/__init__.py +0 -0
  136. oarepo_runtime/services/relations/components.py +0 -15
  137. oarepo_runtime/services/relations/errors.py +0 -18
  138. oarepo_runtime/services/relations/mapping.py +0 -38
  139. oarepo_runtime/services/schema/cf.py +0 -13
  140. oarepo_runtime/services/schema/i18n_validation.py +0 -7
  141. oarepo_runtime/services/schema/marshmallow.py +0 -44
  142. oarepo_runtime/services/schema/marshmallow_to_json_schema.py +0 -72
  143. oarepo_runtime/services/schema/oneofschema.py +0 -192
  144. oarepo_runtime/services/schema/polymorphic.py +0 -21
  145. oarepo_runtime/services/schema/rdm.py +0 -75
  146. oarepo_runtime/services/schema/rdm_ui.py +0 -156
  147. oarepo_runtime/services/schema/ui.py +0 -251
  148. oarepo_runtime/services/schema/validation.py +0 -70
  149. oarepo_runtime/services/search.py +0 -282
  150. oarepo_runtime/services/service.py +0 -61
  151. oarepo_runtime/tasks.py +0 -6
  152. oarepo_runtime/translations/cs/LC_MESSAGES/messages.mo +0 -0
  153. oarepo_runtime/translations/cs/LC_MESSAGES/messages.po +0 -85
  154. oarepo_runtime/translations/default_translations.py +0 -6
  155. oarepo_runtime/translations/en/LC_MESSAGES/messages.mo +0 -0
  156. oarepo_runtime/translations/en/LC_MESSAGES/messages.po +0 -89
  157. oarepo_runtime/translations/messages.pot +0 -91
  158. oarepo_runtime/uow.py +0 -146
  159. oarepo_runtime/utils/__init__.py +0 -0
  160. oarepo_runtime/utils/functools.py +0 -37
  161. oarepo_runtime/utils/identity_utils.py +0 -35
  162. oarepo_runtime/utils/index.py +0 -11
  163. oarepo_runtime/utils/path.py +0 -97
  164. oarepo_runtime-1.10.2.dist-info/RECORD +0 -163
  165. oarepo_runtime-1.10.2.dist-info/entry_points.txt +0 -16
  166. oarepo_runtime-1.10.2.dist-info/top_level.txt +0 -2
  167. tests/marshmallow_to_json/__init__.py +0 -0
  168. tests/marshmallow_to_json/test_datacite_ui_schema.py +0 -1410
  169. tests/marshmallow_to_json/test_simple_schema.py +0 -52
  170. tests/pkg_data/__init__.py +0 -0
  171. {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, value_name, value_field="marshmallow_utils.fields.SanitizedHTML"
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, value, attr=None, obj=None, **kwargs):
53
- if not value:
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 value:
93
+ for v in obj:
57
94
  if language == v[lang_name]:
58
95
  return v[value_name]
59
- return next(iter(value))[value_name]
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: 1.10.2
3
+ Version: 2.0.0.dev3
4
4
  Summary: A set of runtime extensions of Invenio repository
5
- Description-Content-Type: text/markdown
5
+ License-Expression: MIT
6
6
  License-File: LICENSE
7
- Requires-Dist: marshmallow
8
- Requires-Dist: langcodes
9
- Requires-Dist: pyyaml
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 == "dev"
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 == "tests"
24
- Requires-Dist: pytest-oarepo; extra == "tests"
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,,
@@ -1,5 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
-
@@ -0,0 +1,5 @@
1
+ [invenio_base.api_apps]
2
+ oarepo_runtime = oarepo_runtime.ext:OARepoRuntime
3
+
4
+ [invenio_base.apps]
5
+ oarepo_runtime = oarepo_runtime.ext:OARepoRuntime
@@ -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)
@@ -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()
@@ -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))