oarepo-runtime 1.10.3__py3-none-any.whl → 2.0.0.dev4__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 +210 -0
- oarepo_runtime/cli/__init__.py +10 -21
- oarepo_runtime/cli/search.py +34 -0
- oarepo_runtime/config.py +98 -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 +61 -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/facets/__init__.py +12 -33
- oarepo_runtime/services/facets/params.py +45 -110
- 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.3.dist-info → oarepo_runtime-2.0.0.dev4.dist-info}/METADATA +10 -21
- oarepo_runtime-2.0.0.dev4.dist-info/RECORD +32 -0
- {oarepo_runtime-1.10.3.dist-info → oarepo_runtime-2.0.0.dev4.dist-info}/WHEEL +1 -2
- oarepo_runtime-2.0.0.dev4.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/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/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 -146
- 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 -95
- 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 -97
- oarepo_runtime/translations/messages.pot +0 -100
- 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.3.dist-info/RECORD +0 -163
- oarepo_runtime-1.10.3.dist-info/entry_points.txt +0 -16
- oarepo_runtime-1.10.3.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.3.dist-info → oarepo_runtime-2.0.0.dev4.dist-info}/licenses/LICENSE +0 -0
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))
|
oarepo_runtime/cli/fixtures.py
DELETED
@@ -1,167 +0,0 @@
|
|
1
|
-
import click
|
2
|
-
import tqdm
|
3
|
-
from flask import current_app
|
4
|
-
from flask.cli import with_appcontext
|
5
|
-
from flask_principal import Identity, RoleNeed, UserNeed
|
6
|
-
from invenio_access.permissions import any_user, authenticated_user, system_identity
|
7
|
-
from invenio_accounts.models import User
|
8
|
-
|
9
|
-
from oarepo_runtime.cli import oarepo
|
10
|
-
from oarepo_runtime.datastreams import SynchronousDataStream
|
11
|
-
from oarepo_runtime.datastreams.asynchronous import AsynchronousDataStream
|
12
|
-
from oarepo_runtime.datastreams.fixtures import (
|
13
|
-
FixturesCallback,
|
14
|
-
dump_fixtures,
|
15
|
-
fixtures_asynchronous_callback,
|
16
|
-
load_fixtures,
|
17
|
-
)
|
18
|
-
from oarepo_runtime.datastreams.types import StatsKeepingDataStreamCallback
|
19
|
-
|
20
|
-
|
21
|
-
@oarepo.group()
|
22
|
-
def fixtures():
|
23
|
-
"""Load and dump fixtures"""
|
24
|
-
|
25
|
-
|
26
|
-
@fixtures.command()
|
27
|
-
@click.argument("fixture_dir_or_catalogue", required=False)
|
28
|
-
@click.option("--include", multiple=True)
|
29
|
-
@click.option("--exclude", multiple=True)
|
30
|
-
@click.option("--system-fixtures/--no-system-fixtures", default=True, is_flag=True)
|
31
|
-
@click.option("--verbose", is_flag=True)
|
32
|
-
@click.option("--on-background", is_flag=True)
|
33
|
-
@click.option(
|
34
|
-
"--bulk-size",
|
35
|
-
default=100,
|
36
|
-
type=int,
|
37
|
-
help="Size for bulk indexing - this number of records "
|
38
|
-
"will be committed in a single transaction and indexed together",
|
39
|
-
)
|
40
|
-
@click.option("--batch-size", help="Alias for --bulk-size", type=int)
|
41
|
-
@click.option(
|
42
|
-
"--identity", help="Email of the identity that will be used to import the data"
|
43
|
-
)
|
44
|
-
@with_appcontext
|
45
|
-
def load(
|
46
|
-
fixture_dir_or_catalogue=None,
|
47
|
-
include=None,
|
48
|
-
exclude=None,
|
49
|
-
system_fixtures=None,
|
50
|
-
verbose=False,
|
51
|
-
bulk_size=100,
|
52
|
-
on_background=False,
|
53
|
-
batch_size=None,
|
54
|
-
identity=None,
|
55
|
-
):
|
56
|
-
"""Loads fixtures"""
|
57
|
-
if batch_size:
|
58
|
-
bulk_size = batch_size
|
59
|
-
if not on_background:
|
60
|
-
callback = TQDMCallback(verbose=verbose)
|
61
|
-
else:
|
62
|
-
callback = fixtures_asynchronous_callback.s()
|
63
|
-
|
64
|
-
if fixture_dir_or_catalogue:
|
65
|
-
system_fixtures = False
|
66
|
-
|
67
|
-
if not identity:
|
68
|
-
user = None
|
69
|
-
identity = system_identity
|
70
|
-
else:
|
71
|
-
# identity is user email
|
72
|
-
user = User.query.filter_by(email=identity).one()
|
73
|
-
identity = Identity(user.id)
|
74
|
-
|
75
|
-
# TODO: add provides. How to do it better? It seems that we can not use
|
76
|
-
# flask signals to add these, as they depend on request context that is
|
77
|
-
# not available here
|
78
|
-
identity.provides.add(any_user)
|
79
|
-
identity.provides.add(authenticated_user)
|
80
|
-
identity.provides.add(UserNeed(user.id))
|
81
|
-
for role in getattr(user, "roles", []):
|
82
|
-
identity.provides.add(RoleNeed(role.name))
|
83
|
-
# TODO: community roles ...
|
84
|
-
|
85
|
-
with current_app.wsgi_app.mounts["/api"].app_context():
|
86
|
-
load_fixtures(
|
87
|
-
fixture_dir_or_catalogue,
|
88
|
-
_make_list(include),
|
89
|
-
_make_list(exclude),
|
90
|
-
system_fixtures=system_fixtures,
|
91
|
-
callback=callback,
|
92
|
-
batch_size=bulk_size,
|
93
|
-
datastreams_impl=(
|
94
|
-
AsynchronousDataStream if on_background else SynchronousDataStream
|
95
|
-
),
|
96
|
-
identity=identity,
|
97
|
-
)
|
98
|
-
if not on_background:
|
99
|
-
_show_stats(callback, "Load fixtures")
|
100
|
-
|
101
|
-
|
102
|
-
@fixtures.command()
|
103
|
-
@click.option("--include", multiple=True)
|
104
|
-
@click.option("--exclude", multiple=True)
|
105
|
-
@click.argument("fixture_dir", required=True)
|
106
|
-
@click.option("--verbose", is_flag=True)
|
107
|
-
@with_appcontext
|
108
|
-
def dump(fixture_dir, include, exclude, verbose):
|
109
|
-
"""Dump fixtures"""
|
110
|
-
callback = TQDMCallback(verbose=verbose)
|
111
|
-
|
112
|
-
with current_app.wsgi_app.mounts["/api"].app_context():
|
113
|
-
dump_fixtures(
|
114
|
-
fixture_dir,
|
115
|
-
_make_list(include),
|
116
|
-
_make_list(exclude),
|
117
|
-
callback=TQDMCallback(verbose=verbose),
|
118
|
-
)
|
119
|
-
_show_stats(callback, "Dump fixtures")
|
120
|
-
|
121
|
-
|
122
|
-
def _make_list(lst):
|
123
|
-
return [
|
124
|
-
item.strip() for lst_item in lst for item in lst_item.split(",") if item.strip()
|
125
|
-
]
|
126
|
-
|
127
|
-
|
128
|
-
def _show_stats(callback: StatsKeepingDataStreamCallback, title: str):
|
129
|
-
print("\n\n")
|
130
|
-
print(f"{title} stats:")
|
131
|
-
print(callback.stats())
|
132
|
-
|
133
|
-
|
134
|
-
class TQDMCallback(FixturesCallback):
|
135
|
-
def __init__(self, message_prefix="Loading ", verbose=False):
|
136
|
-
super().__init__()
|
137
|
-
self._tqdm = tqdm.tqdm(unit=" item(s)")
|
138
|
-
self._message_prefix = message_prefix
|
139
|
-
self._verbose = verbose
|
140
|
-
|
141
|
-
def fixture_started(self, fixture_name):
|
142
|
-
self._tqdm.set_description(f"{self._message_prefix}{fixture_name} running")
|
143
|
-
|
144
|
-
def fixture_finished(self, fixture_name):
|
145
|
-
self._tqdm.set_description(f"{self._message_prefix}{fixture_name} finished")
|
146
|
-
|
147
|
-
def batch_finished(self, batch):
|
148
|
-
super().batch_finished(batch)
|
149
|
-
self._tqdm.update(len(batch.entries))
|
150
|
-
for err in batch.errors:
|
151
|
-
self._tqdm.write("Failed batch: {}: {}".format(err, batch))
|
152
|
-
if self._verbose:
|
153
|
-
for entry in batch.entries:
|
154
|
-
if entry.errors:
|
155
|
-
self._tqdm.write("Failed entry: {}".format(entry))
|
156
|
-
|
157
|
-
def reader_error(self, reader, exception):
|
158
|
-
super().reader_error(reader, exception)
|
159
|
-
self._tqdm.write("Reader error:{}: {}".format(reader, exception))
|
160
|
-
|
161
|
-
def transformer_error(self, batch, transformer, exception):
|
162
|
-
super().transformer_error(batch, transformer, exception)
|
163
|
-
self._tqdm.write("Transformer error: {}: {}".format(transformer, exception))
|
164
|
-
|
165
|
-
def writer_error(self, batch, writer, exception):
|
166
|
-
super().writer_error(batch, writer, exception)
|
167
|
-
self._tqdm.write("Writer error: {}: {}".format(writer, exception))
|