oarepo-runtime 2.0.0.dev25__py3-none-any.whl → 2.0.0.dev28__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 +1 -1
- oarepo_runtime/api.py +3 -0
- oarepo_runtime/info/__init__.py +11 -0
- oarepo_runtime/info/views.py +440 -0
- oarepo_runtime/services/generators.py +2 -2
- {oarepo_runtime-2.0.0.dev25.dist-info → oarepo_runtime-2.0.0.dev28.dist-info}/METADATA +5 -1
- {oarepo_runtime-2.0.0.dev25.dist-info → oarepo_runtime-2.0.0.dev28.dist-info}/RECORD +10 -8
- {oarepo_runtime-2.0.0.dev25.dist-info → oarepo_runtime-2.0.0.dev28.dist-info}/WHEEL +0 -0
- {oarepo_runtime-2.0.0.dev25.dist-info → oarepo_runtime-2.0.0.dev28.dist-info}/entry_points.txt +0 -0
- {oarepo_runtime-2.0.0.dev25.dist-info → oarepo_runtime-2.0.0.dev28.dist-info}/licenses/LICENSE +0 -0
oarepo_runtime/__init__.py
CHANGED
oarepo_runtime/api.py
CHANGED
@@ -88,6 +88,9 @@ class Export:
|
|
88
88
|
oai_namespace: str | None = None
|
89
89
|
"""OAI namespace, if applicable. If not set, the export can not be used in OAI-PMH responses."""
|
90
90
|
|
91
|
+
description: LazyString | None = None
|
92
|
+
"""Description of the export format, human readable."""
|
93
|
+
|
91
94
|
|
92
95
|
class Model[
|
93
96
|
S: RecordService = RecordService,
|
@@ -0,0 +1,11 @@
|
|
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
|
+
"""Info module."""
|
10
|
+
|
11
|
+
from __future__ import annotations
|
@@ -0,0 +1,440 @@
|
|
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
|
+
# TODO: better docstring
|
10
|
+
"""Info Resource."""
|
11
|
+
|
12
|
+
from __future__ import annotations
|
13
|
+
|
14
|
+
import importlib
|
15
|
+
import logging
|
16
|
+
import os
|
17
|
+
import re
|
18
|
+
from functools import cached_property
|
19
|
+
from typing import TYPE_CHECKING, Any, ClassVar, cast
|
20
|
+
from urllib.parse import urljoin, urlparse, urlunparse
|
21
|
+
|
22
|
+
import marshmallow as ma
|
23
|
+
from flask import Blueprint, Flask, current_app, request, url_for
|
24
|
+
from flask_resources import (
|
25
|
+
Resource,
|
26
|
+
ResourceConfig,
|
27
|
+
from_conf,
|
28
|
+
request_parser,
|
29
|
+
resource_requestctx,
|
30
|
+
response_handler,
|
31
|
+
route,
|
32
|
+
)
|
33
|
+
from invenio_base import invenio_url_for
|
34
|
+
from invenio_base.utils import obj_or_import_string
|
35
|
+
from invenio_jsonschemas import current_jsonschemas
|
36
|
+
from invenio_records_resources.proxies import (
|
37
|
+
current_transfer_registry,
|
38
|
+
)
|
39
|
+
from werkzeug.routing import BuildError
|
40
|
+
|
41
|
+
if TYPE_CHECKING:
|
42
|
+
from invenio_records.systemfields import ConstantField
|
43
|
+
from invenio_records_resources.records.api import Record
|
44
|
+
|
45
|
+
from oarepo_runtime import Model
|
46
|
+
from oarepo_runtime.proxies import current_runtime
|
47
|
+
|
48
|
+
logger = logging.getLogger("oarepo_runtime.info")
|
49
|
+
|
50
|
+
|
51
|
+
class InfoConfig(ResourceConfig):
|
52
|
+
"""Info resource config."""
|
53
|
+
|
54
|
+
blueprint_name = "oarepo_runtime_info"
|
55
|
+
url_prefix = "/.well-known/repository"
|
56
|
+
|
57
|
+
schema_view_args: ClassVar[dict[str, ma.fields.Str]] = {"schema": ma.fields.Str()}
|
58
|
+
model_view_args: ClassVar[dict[str, ma.fields.Str]] = {"model": ma.fields.Str()}
|
59
|
+
|
60
|
+
def __init__(self, app: Flask):
|
61
|
+
"""Initialize Info config."""
|
62
|
+
self.app = app
|
63
|
+
|
64
|
+
@cached_property
|
65
|
+
def components(self) -> tuple[object, ...]:
|
66
|
+
"""Get the components for the info resource from config."""
|
67
|
+
return tuple(obj_or_import_string(x) for x in self.app.config.get("INFO_ENDPOINT_COMPONENTS", []))
|
68
|
+
|
69
|
+
|
70
|
+
schema_view_args = request_parser(from_conf("schema_view_args"), location="view_args")
|
71
|
+
model_view_args = request_parser(from_conf("model_view_args"), location="view_args")
|
72
|
+
|
73
|
+
|
74
|
+
class InfoResource(Resource):
|
75
|
+
"""Info resource."""
|
76
|
+
|
77
|
+
def create_url_rules(self) -> list[dict[str, Any]]:
|
78
|
+
"""Create the URL rules for the info resource."""
|
79
|
+
return [
|
80
|
+
route("GET", "/", self.repository),
|
81
|
+
route("GET", "/models", self.models),
|
82
|
+
route("GET", "/schema/<path:schema>", self.schema),
|
83
|
+
]
|
84
|
+
|
85
|
+
def call_components(self, method_name: str, **kwargs: Any) -> None:
|
86
|
+
"""Call components for the given method name."""
|
87
|
+
for component in self.components:
|
88
|
+
if hasattr(component, method_name):
|
89
|
+
getattr(component, method_name)(**kwargs)
|
90
|
+
|
91
|
+
@cached_property
|
92
|
+
def components(self) -> list[Any]:
|
93
|
+
"""Get the components for the info resource from config."""
|
94
|
+
return [x(self) for x in self.config.components]
|
95
|
+
|
96
|
+
@response_handler(many=True)
|
97
|
+
def models(self) -> tuple[list[dict], int]:
|
98
|
+
"""Models endpoint."""
|
99
|
+
return self.model_data + self.vocabulary_data, 200
|
100
|
+
|
101
|
+
@schema_view_args
|
102
|
+
@response_handler()
|
103
|
+
def schema(self) -> tuple[dict, int]:
|
104
|
+
"""Return jsonschema for the current schema."""
|
105
|
+
schema = resource_requestctx.view_args["schema"]
|
106
|
+
return current_jsonschemas.get_schema(schema, resolved=True), 200
|
107
|
+
|
108
|
+
def _get_model_content_types(self, model: Model) -> list[dict]:
|
109
|
+
"""Get the content types supported by the model.
|
110
|
+
|
111
|
+
Returns a list of:
|
112
|
+
|
113
|
+
content_type="application/json",
|
114
|
+
name="Invenio RDM JSON",
|
115
|
+
description="Invenio RDM JSON as described in",
|
116
|
+
schema=url / "schemas" / "records" / "record-v6.0.0.json",
|
117
|
+
can_export=True,
|
118
|
+
can_deposit=True,
|
119
|
+
"""
|
120
|
+
content_types: list[dict] = []
|
121
|
+
# export content types
|
122
|
+
for model_export in model.exports:
|
123
|
+
curr_item = {
|
124
|
+
"content_type": model_export.mimetype,
|
125
|
+
"code": model_export.code,
|
126
|
+
"name": model_export.name,
|
127
|
+
"description": model_export.description,
|
128
|
+
"can_export": True,
|
129
|
+
"can_deposit": model_export.mimetype == "application/json",
|
130
|
+
}
|
131
|
+
if model_export.mimetype == "application/json":
|
132
|
+
curr_item["schema"] = url_for(
|
133
|
+
"oarepo_runtime_info.schema",
|
134
|
+
schema=model.record_json_schema.replace("local://", ""),
|
135
|
+
_external=True,
|
136
|
+
)
|
137
|
+
content_types.append(curr_item)
|
138
|
+
return content_types
|
139
|
+
|
140
|
+
def _get_model_features(self, model: Model) -> list[str]:
|
141
|
+
"""Get a list of features supported by the model."""
|
142
|
+
feature_keys = []
|
143
|
+
model_features = model.features or {}
|
144
|
+
if model_features.get("requests", {}):
|
145
|
+
feature_keys.append("requests")
|
146
|
+
if model_features.get("draft", {}):
|
147
|
+
feature_keys.append("drafts")
|
148
|
+
if model_features.get("files", {}):
|
149
|
+
feature_keys.append("files")
|
150
|
+
return feature_keys
|
151
|
+
|
152
|
+
def _get_model_html_endpoint(self, model: Model) -> Any:
|
153
|
+
base = self._get_model_api_endpoint(model)
|
154
|
+
if not base:
|
155
|
+
return None
|
156
|
+
suffix = model.resource_config.url_prefix or ""
|
157
|
+
return urljoin(base, suffix)
|
158
|
+
|
159
|
+
def _get_model_api_endpoint(self, model: Model) -> str | None:
|
160
|
+
try:
|
161
|
+
alias = model.api_blueprint_name
|
162
|
+
return model.api_url("search", type=alias, _external=True)
|
163
|
+
except BuildError:
|
164
|
+
logger.exception("Failed to get model api endpoint")
|
165
|
+
return None
|
166
|
+
|
167
|
+
def _get_model_draft_endpoint(self, model: Model) -> str | None:
|
168
|
+
try:
|
169
|
+
alias = model.api_blueprint_name
|
170
|
+
return model.api_url("search_user_records", type=alias, _external=True)
|
171
|
+
except BuildError:
|
172
|
+
logger.exception("Failed to get model draft endpoint")
|
173
|
+
return None
|
174
|
+
|
175
|
+
@cached_property
|
176
|
+
def model_data(self) -> list[dict]:
|
177
|
+
"""Get the model data."""
|
178
|
+
data: list[dict] = []
|
179
|
+
# iterate entrypoint oarepo.models
|
180
|
+
for model in current_runtime.rdm_models:
|
181
|
+
service = model.service
|
182
|
+
service_class = model.service.__class__
|
183
|
+
if not service or not isinstance(service, service_class):
|
184
|
+
continue
|
185
|
+
|
186
|
+
model_features = self._get_model_features(model)
|
187
|
+
|
188
|
+
links: dict[str, str | None] = {
|
189
|
+
"html": self._get_model_html_endpoint(model),
|
190
|
+
"records": self._get_model_api_endpoint(model),
|
191
|
+
"deposit": self._get_model_api_endpoint(model),
|
192
|
+
}
|
193
|
+
|
194
|
+
if "drafts" in model_features:
|
195
|
+
links["drafts"] = self._get_model_draft_endpoint(model)
|
196
|
+
|
197
|
+
data.append(
|
198
|
+
{
|
199
|
+
"schema": model.record_json_schema,
|
200
|
+
# TODO: stejna hodnota jako nasledujici prop name, je to spravne?
|
201
|
+
"type": model.name,
|
202
|
+
"name": model.name,
|
203
|
+
"description": model.description,
|
204
|
+
"version": model.version,
|
205
|
+
"features": model_features,
|
206
|
+
"links": links,
|
207
|
+
"content_types": self._get_model_content_types(model),
|
208
|
+
# rdm models always have metadata element
|
209
|
+
"metadata": True,
|
210
|
+
}
|
211
|
+
)
|
212
|
+
self.call_components("model", data=data)
|
213
|
+
data.sort(key=lambda x: x["type"])
|
214
|
+
return data
|
215
|
+
|
216
|
+
@cached_property
|
217
|
+
def vocabulary_data(self) -> list[dict]:
|
218
|
+
"""Get the vocabulary data."""
|
219
|
+
ret: list[dict] = []
|
220
|
+
try:
|
221
|
+
from invenio_vocabularies.contrib.affiliations.api import Affiliation
|
222
|
+
from invenio_vocabularies.contrib.awards.api import Award
|
223
|
+
from invenio_vocabularies.contrib.funders.api import Funder
|
224
|
+
from invenio_vocabularies.contrib.names.api import Name
|
225
|
+
from invenio_vocabularies.contrib.subjects.api import Subject
|
226
|
+
from invenio_vocabularies.records.api import Vocabulary
|
227
|
+
from invenio_vocabularies.records.models import VocabularyType
|
228
|
+
except ImportError: # pragma: no cover
|
229
|
+
return ret
|
230
|
+
|
231
|
+
def _generate_rdm_vocabulary( # noqa: PLR0913 more attributes
|
232
|
+
base_url: str,
|
233
|
+
record: type[Record],
|
234
|
+
vocabulary_type: str,
|
235
|
+
vocabulary_name: str,
|
236
|
+
vocabulary_description: str,
|
237
|
+
special: bool,
|
238
|
+
can_export: bool = True,
|
239
|
+
can_deposit: bool = False,
|
240
|
+
) -> dict:
|
241
|
+
schema_field = cast("ConstantField[Record, str] | None", getattr(record, "schema", None))
|
242
|
+
if schema_field is not None:
|
243
|
+
schema_field_value = schema_field.value
|
244
|
+
schema_path = base_url + schema_field_value.replace("local://", "")
|
245
|
+
else:
|
246
|
+
raise ValueError(f"Record {record} has no schema field") # pragma: no cover
|
247
|
+
|
248
|
+
if not base_url.endswith("/"):
|
249
|
+
base_url += "/"
|
250
|
+
url_prefix = base_url + "api" if special else base_url + "api/vocabularies"
|
251
|
+
links = {
|
252
|
+
"records": f"{url_prefix}/{vocabulary_type}",
|
253
|
+
}
|
254
|
+
if can_deposit:
|
255
|
+
links["deposit"] = f"{url_prefix}/{vocabulary_type}"
|
256
|
+
|
257
|
+
return {
|
258
|
+
"schema": schema_field_value,
|
259
|
+
"type": vocabulary_type,
|
260
|
+
"name": vocabulary_name,
|
261
|
+
"description": vocabulary_description,
|
262
|
+
"version": "unknown",
|
263
|
+
"features": ["rdm", "vocabulary"],
|
264
|
+
"links": links,
|
265
|
+
"content_types": [
|
266
|
+
{
|
267
|
+
"content_type": "application/json",
|
268
|
+
"name": "Invenio RDM JSON",
|
269
|
+
"description": "Vocabulary JSON",
|
270
|
+
"schema": schema_path,
|
271
|
+
"can_export": can_export,
|
272
|
+
"can_deposit": can_deposit,
|
273
|
+
}
|
274
|
+
],
|
275
|
+
"metadata": False,
|
276
|
+
}
|
277
|
+
|
278
|
+
base_url = invenio_url_for("vocabularies.search", type="languages", _external=True)
|
279
|
+
base_url = replace_path_in_url(base_url, "/")
|
280
|
+
ret = [
|
281
|
+
_generate_rdm_vocabulary(base_url, Affiliation, "affiliations", "Affiliations", "", special=True),
|
282
|
+
_generate_rdm_vocabulary(base_url, Award, "awards", "Awards", "", special=True),
|
283
|
+
_generate_rdm_vocabulary(base_url, Funder, "funders", "Funders", "", special=True),
|
284
|
+
_generate_rdm_vocabulary(base_url, Subject, "subjects", "Subjects", "", special=True),
|
285
|
+
_generate_rdm_vocabulary(base_url, Name, "names", "Names", "", special=True),
|
286
|
+
_generate_rdm_vocabulary(
|
287
|
+
base_url,
|
288
|
+
Affiliation,
|
289
|
+
"affiliations-vocab",
|
290
|
+
"Affiliations",
|
291
|
+
"Specialized vocabulary for affiliations",
|
292
|
+
special=False,
|
293
|
+
can_deposit=True,
|
294
|
+
),
|
295
|
+
_generate_rdm_vocabulary(
|
296
|
+
base_url,
|
297
|
+
Award,
|
298
|
+
"awards-vocab",
|
299
|
+
"Awards",
|
300
|
+
"Specialized vocabulary for awards",
|
301
|
+
special=False,
|
302
|
+
can_deposit=True,
|
303
|
+
),
|
304
|
+
_generate_rdm_vocabulary(
|
305
|
+
base_url,
|
306
|
+
Funder,
|
307
|
+
"funders-vocab",
|
308
|
+
"Funders",
|
309
|
+
"Specialized vocabulary for funders",
|
310
|
+
special=False,
|
311
|
+
can_deposit=True,
|
312
|
+
),
|
313
|
+
_generate_rdm_vocabulary(
|
314
|
+
base_url,
|
315
|
+
Subject,
|
316
|
+
"subjects-vocab",
|
317
|
+
"Subjects",
|
318
|
+
"Specialized vocabulary for subjects",
|
319
|
+
special=False,
|
320
|
+
can_deposit=True,
|
321
|
+
),
|
322
|
+
_generate_rdm_vocabulary(
|
323
|
+
base_url,
|
324
|
+
Name,
|
325
|
+
"names-vocab",
|
326
|
+
"Names",
|
327
|
+
"Specialized vocabulary for names",
|
328
|
+
special=False,
|
329
|
+
can_deposit=True,
|
330
|
+
),
|
331
|
+
]
|
332
|
+
|
333
|
+
vc_types = {vc.id for vc in cast("Any", VocabularyType).query.all()}
|
334
|
+
vocab_type_metadata = current_app.config.get("INVENIO_VOCABULARY_TYPE_METADATA", {})
|
335
|
+
vc_types.update(vocab_type_metadata.keys())
|
336
|
+
|
337
|
+
for vc in sorted(vc_types):
|
338
|
+
vc_metadata = vocab_type_metadata.get(vc, {})
|
339
|
+
ret.append(
|
340
|
+
_generate_rdm_vocabulary(
|
341
|
+
base_url,
|
342
|
+
Vocabulary,
|
343
|
+
vc,
|
344
|
+
to_current_language(vc_metadata.get("name")) or vc,
|
345
|
+
to_current_language(vc_metadata.get("description")) or "",
|
346
|
+
special=False,
|
347
|
+
can_export=True,
|
348
|
+
can_deposit=True,
|
349
|
+
)
|
350
|
+
)
|
351
|
+
|
352
|
+
return ret
|
353
|
+
|
354
|
+
@response_handler()
|
355
|
+
def repository(self) -> tuple[dict, int]:
|
356
|
+
"""Repository endpoint."""
|
357
|
+
endpoint = request.endpoint
|
358
|
+
self_url = url_for(endpoint, _external=True) if endpoint else request.url
|
359
|
+
links = {
|
360
|
+
"self": self_url,
|
361
|
+
"api": replace_path_in_url(self_url, "/api"),
|
362
|
+
"models": url_for("oarepo_runtime_info.models", _external=True),
|
363
|
+
}
|
364
|
+
try:
|
365
|
+
import invenio_requests # noqa
|
366
|
+
|
367
|
+
links["requests"] = invenio_url_for("requests.search")
|
368
|
+
except ImportError: # pragma: no cover
|
369
|
+
pass
|
370
|
+
|
371
|
+
ret = {
|
372
|
+
"schema": "local://introspection-v1.0.0",
|
373
|
+
"name": current_app.config.get("THEME_SITENAME", ""),
|
374
|
+
"description": current_app.config.get("REPOSITORY_DESCRIPTION", ""),
|
375
|
+
"version": os.environ.get("DEPLOYMENT_VERSION", "local development"),
|
376
|
+
"invenio_version": get_package_version("oarepo"),
|
377
|
+
"transfers": list(current_transfer_registry.get_transfer_types()),
|
378
|
+
"links": links,
|
379
|
+
"features": [
|
380
|
+
*_add_feature_if_can_import("drafts", "invenio_drafts_resources"),
|
381
|
+
*_add_feature_if_can_import("workflows", "oarepo_workflows"),
|
382
|
+
*_add_feature_if_can_import("requests", "invenio_requests"),
|
383
|
+
*_add_feature_if_can_import("communities", "invenio_communities"),
|
384
|
+
*_add_feature_if_can_import("request_types", "oarepo_requests"),
|
385
|
+
],
|
386
|
+
}
|
387
|
+
if len(self.model_data) == 1:
|
388
|
+
ret["default_model"] = self.model_data[0]["name"]
|
389
|
+
|
390
|
+
self.call_components("repository", data=ret)
|
391
|
+
return ret, 200
|
392
|
+
|
393
|
+
|
394
|
+
def create_wellknown_blueprint(app: Flask) -> Blueprint:
|
395
|
+
"""Create an info blueprint."""
|
396
|
+
info_endpoint_config = app.config.get("INFO_ENDPOINT_CONFIG")
|
397
|
+
config_class = (
|
398
|
+
cast("type[InfoConfig]", obj_or_import_string(info_endpoint_config)) if info_endpoint_config else InfoConfig
|
399
|
+
)
|
400
|
+
|
401
|
+
return InfoResource(config=config_class(app)).as_blueprint()
|
402
|
+
|
403
|
+
|
404
|
+
def get_package_version(package_name: str) -> str | None:
|
405
|
+
"""Get package version."""
|
406
|
+
from pkg_resources import get_distribution
|
407
|
+
|
408
|
+
return re.sub(r"\+.*", "", get_distribution(package_name).version)
|
409
|
+
|
410
|
+
|
411
|
+
def replace_path_in_url(url: str, path: str) -> str:
|
412
|
+
"""Replace the path in a URL."""
|
413
|
+
# Parse the URL into its components
|
414
|
+
parsed_url = urlparse(url)
|
415
|
+
|
416
|
+
# Replace the path with '/api'
|
417
|
+
new_parsed_url = parsed_url._replace(path=path)
|
418
|
+
|
419
|
+
# Return the reconstructed URL with the new path
|
420
|
+
return str(urlunparse(new_parsed_url))
|
421
|
+
|
422
|
+
|
423
|
+
def _add_feature_if_can_import(feature: str, module: str) -> list[str]:
|
424
|
+
try:
|
425
|
+
importlib.import_module(module)
|
426
|
+
except ImportError:
|
427
|
+
return []
|
428
|
+
else:
|
429
|
+
return [feature]
|
430
|
+
|
431
|
+
|
432
|
+
def to_current_language(data: dict | Any) -> Any:
|
433
|
+
"""Convert data to current language."""
|
434
|
+
if isinstance(data, dict):
|
435
|
+
from flask_babel import get_locale
|
436
|
+
|
437
|
+
current_locale = get_locale()
|
438
|
+
if current_locale:
|
439
|
+
return data.get(current_locale.language)
|
440
|
+
return data
|
@@ -67,11 +67,11 @@ class ConditionalGenerator(InvenioConditionalGenerator, ABC):
|
|
67
67
|
|
68
68
|
@override
|
69
69
|
def needs(self, record: Record | None = None, **kwargs: Any) -> Collection[Need]:
|
70
|
-
return super().needs(**kwargs) # type: ignore[no-any-return] # mypy bug ?
|
70
|
+
return super().needs(record=record, **kwargs) # type: ignore[no-any-return] # mypy bug ?
|
71
71
|
|
72
72
|
@override
|
73
73
|
def excludes(self, record: Record | None = None, **kwargs: Any) -> Collection[Need]:
|
74
|
-
return super().excludes(**kwargs) # type: ignore[no-any-return] # mypy bug ?
|
74
|
+
return super().excludes(record=record, **kwargs) # type: ignore[no-any-return] # mypy bug ?
|
75
75
|
|
76
76
|
@abstractmethod
|
77
77
|
def _query_instate(self, **context: Any) -> dsl.query.Query:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: oarepo-runtime
|
3
|
-
Version: 2.0.0.
|
3
|
+
Version: 2.0.0.dev28
|
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
|
@@ -11,6 +11,10 @@ Requires-Dist: oarepo[rdm,tests]<15,>=13
|
|
11
11
|
Provides-Extra: dev
|
12
12
|
Requires-Dist: oarepo-invenio-typing-stubs>=0.1.0; extra == 'dev'
|
13
13
|
Requires-Dist: pytest>=7.1.2; extra == 'dev'
|
14
|
+
Provides-Extra: oarepo13
|
15
|
+
Requires-Dist: oarepo[rdm]<14,>=13; extra == 'oarepo13'
|
16
|
+
Provides-Extra: oarepo14
|
17
|
+
Requires-Dist: oarepo[rdm]<15,>=14; extra == 'oarepo14'
|
14
18
|
Provides-Extra: tests
|
15
19
|
Requires-Dist: pytest>=7.1.2; extra == 'tests'
|
16
20
|
Description-Content-Type: text/markdown
|
@@ -1,5 +1,5 @@
|
|
1
|
-
oarepo_runtime/__init__.py,sha256=
|
2
|
-
oarepo_runtime/api.py,sha256=
|
1
|
+
oarepo_runtime/__init__.py,sha256=SB5ZZKCuzkUbuBlw_ngzm1suKgwrWG8OMXF4hw49T5Y,686
|
2
|
+
oarepo_runtime/api.py,sha256=5MjhNwwjbbS7w7aql6pg8haKvqqr8QBmZBqJkWRWEw4,13237
|
3
3
|
oarepo_runtime/config.py,sha256=RUEPFn_5bKp9Wb0OY-Fb3VK30m35vF5IsLjYaQHhP3g,3838
|
4
4
|
oarepo_runtime/ext.py,sha256=NgiRNl_hwTvEWcXnNwVh_XCPJyvwr3dZkdPmkWvN1xo,8785
|
5
5
|
oarepo_runtime/proxies.py,sha256=JhOklHoJO8-gPamvjY6jtF9tlOrvcuBXG9kVHPO-x3Q,782
|
@@ -7,6 +7,8 @@ oarepo_runtime/py.typed,sha256=RznSCjXReEUI9zkmD25E8XniG_MvPpLBF6MyNZA8MmE,42
|
|
7
7
|
oarepo_runtime/typing.py,sha256=vH8UUb4QTJowuvibwHaOOEwxx8i21LcOeplxJl0Yrew,1594
|
8
8
|
oarepo_runtime/cli/__init__.py,sha256=H7GOeOBf0udgKWOdlAQswIMvRrD8BwcEjOVxIqP0Suw,731
|
9
9
|
oarepo_runtime/cli/search.py,sha256=4fHkrjltUUPVUzJiuWaiWxTk62rIYxal3_3jRsZVMmI,1175
|
10
|
+
oarepo_runtime/info/__init__.py,sha256=qRG3mSyoiw7sKm9StiuBJs6l15HrdAQ4sphsAQsJtQc,336
|
11
|
+
oarepo_runtime/info/views.py,sha256=PRfVaSsrQywE0lDpiLgDkor0xWzzYEQPkgHW7ITtQAc,16339
|
10
12
|
oarepo_runtime/records/__init__.py,sha256=AbWzmVCY7MhrpdEeI0e3lKzeugPMUSo8T08-NBVeig4,339
|
11
13
|
oarepo_runtime/records/drafts.py,sha256=b45ROjd9lwy6ratrpAruimcKvQmJradk5JgILoBAHmY,1965
|
12
14
|
oarepo_runtime/records/mapping.py,sha256=fn6M208axxBqHtRV6qKQukwUw1z0hq_KF4qfuB2rr98,2630
|
@@ -19,7 +21,7 @@ oarepo_runtime/records/systemfields/selectors.py,sha256=ijVDwAXaXTV5NtcXsrALkhdd
|
|
19
21
|
oarepo_runtime/resources/__init__.py,sha256=voynQULXoOEviADkbOpekMphZPTAz4IOTg5BF9xPwTM,453
|
20
22
|
oarepo_runtime/resources/config.py,sha256=hJewyZ2FlEm4TtYnQS9JsnKnA6hhtSbvo1PC24-7f7Y,980
|
21
23
|
oarepo_runtime/services/__init__.py,sha256=OGtBgEeaDTyk2RPDNXuKbU9_7egFBZr42SM0gN5FrF4,341
|
22
|
-
oarepo_runtime/services/generators.py,sha256=
|
24
|
+
oarepo_runtime/services/generators.py,sha256=8Z2QGzob4c2vaaNqhcMZsRybmwtOt30Plgf3EFmcJXw,4622
|
23
25
|
oarepo_runtime/services/results.py,sha256=qzoIQW5-ShL1YJDgPjfTlPnsgfEZhojNehhHNTUxRgI,7120
|
24
26
|
oarepo_runtime/services/config/__init__.py,sha256=SX1kfIGk8HkohdLQrNpRQUTltksEyDcCa-kFXxrX4e8,711
|
25
27
|
oarepo_runtime/services/config/components.py,sha256=cyU-JeMzLuBL-9JkUKbUQuu527WAq0yptGs6806XSho,23039
|
@@ -39,8 +41,8 @@ oarepo_runtime/services/schema/__init__.py,sha256=jgAPI_uKC6Ug4KQWnwQVg3-aNaw-eH
|
|
39
41
|
oarepo_runtime/services/schema/i18n.py,sha256=9D1zOQaPKAnYzejB0vO-m2BJYnam0N0Lrq4jID7twfE,3174
|
40
42
|
oarepo_runtime/services/schema/i18n_ui.py,sha256=DbusphhGDeaobTt4nuwNgKZ6Houlu4Sv3SuMGkdjRRY,3582
|
41
43
|
oarepo_runtime/services/schema/ui.py,sha256=6HPRMOytE7UQnGd4Z21kvYTpX5p_g2TmP2_v4pwkU8w,4524
|
42
|
-
oarepo_runtime-2.0.0.
|
43
|
-
oarepo_runtime-2.0.0.
|
44
|
-
oarepo_runtime-2.0.0.
|
45
|
-
oarepo_runtime-2.0.0.
|
46
|
-
oarepo_runtime-2.0.0.
|
44
|
+
oarepo_runtime-2.0.0.dev28.dist-info/METADATA,sha256=p_h3OTOgDOBbAPP19O2iOVtCxMf7dc48yVRcz42O1yY,4723
|
45
|
+
oarepo_runtime-2.0.0.dev28.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
46
|
+
oarepo_runtime-2.0.0.dev28.dist-info/entry_points.txt,sha256=rOfs8R1oXFN_dLH9zAZ6ydkvr83mDajegc6NBIRsCMQ,318
|
47
|
+
oarepo_runtime-2.0.0.dev28.dist-info/licenses/LICENSE,sha256=h2uWz0OaB3EN-J1ImdGJZzc7yvfQjvHVYdUhQ-H7ypY,1064
|
48
|
+
oarepo_runtime-2.0.0.dev28.dist-info/RECORD,,
|
File without changes
|
{oarepo_runtime-2.0.0.dev25.dist-info → oarepo_runtime-2.0.0.dev28.dist-info}/entry_points.txt
RENAMED
File without changes
|
{oarepo_runtime-2.0.0.dev25.dist-info → oarepo_runtime-2.0.0.dev28.dist-info}/licenses/LICENSE
RENAMED
File without changes
|