rudi-node-write 1.2.1__tar.gz → 1.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {rudi_node_write-1.2.1/src/rudi_node_write.egg-info → rudi_node_write-1.2.2}/PKG-INFO +24 -1
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/pyproject.toml +5 -4
- rudi_node_write-1.2.2/requirements-dev.txt +102 -0
- rudi_node_write-1.2.2/requirements.txt +6 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/utils/list_utils.py +13 -13
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2/src/rudi_node_write.egg-info}/PKG-INFO +24 -1
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write.egg-info/SOURCES.txt +2 -3
- rudi_node_write-1.2.2/src/rudi_node_write.egg-info/requires.txt +24 -0
- rudi_node_write-1.2.1/requirements.txt +0 -0
- rudi_node_write-1.2.1/src/rudi_node_write/wip/clean_node.py +0 -50
- rudi_node_write-1.2.1/src/rudi_node_write/wip/federation_backup.py +0 -145
- rudi_node_write-1.2.1/src/rudi_node_write/wip/rudinode_federation.py +0 -412
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/LICENCE.md +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/README.md +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/setup.cfg +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/__init__.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/conf/meta_defaults.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/connectors/io_connector.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/connectors/io_rudi_api_write.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/connectors/io_rudi_jwt_factory.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/connectors/io_rudi_manager_write.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/connectors/io_rudi_media_write.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/connectors/rudi_node_auth.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/rudi_node_writer.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/rudi_types/rudi_const.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/rudi_types/rudi_contact.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/rudi_types/rudi_dates.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/rudi_types/rudi_dictionary_entry.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/rudi_types/rudi_geo.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/rudi_types/rudi_licence.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/rudi_types/rudi_media.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/rudi_types/rudi_meta.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/rudi_types/rudi_meta_misc.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/rudi_types/rudi_org.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/rudi_types/serializable.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/utils/dict_utils.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/utils/err.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/utils/file_utils.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/utils/html_utils.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/utils/jwt.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/utils/log.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/utils/str_utils.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/utils/type_date.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/utils/typing_utils.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/utils/url_utils.py +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write.egg-info/dependency_links.txt +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write.egg-info/top_level.txt +0 -0
- {rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/tests/test_rudi_node_write.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: rudi-node-write
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.2
|
|
4
4
|
Summary: Use the internal API of a RUDI Producer node
|
|
5
5
|
Author-email: Olivier Martineau <olivier.martineau@irisa.fr>
|
|
6
6
|
Maintainer-email: Olivier Martineau <olivier.martineau@irisa.fr>
|
|
@@ -17,6 +17,29 @@ Classifier: License :: OSI Approved :: European Union Public Licence 1.2 (EUPL 1
|
|
|
17
17
|
Requires-Python: >=3.11
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
19
|
License-File: LICENCE.md
|
|
20
|
+
Requires-Dist: beautifulsoup4==4.12.3
|
|
21
|
+
Requires-Dist: chardet==5.2.0
|
|
22
|
+
Requires-Dist: deepdiff==8.0.1
|
|
23
|
+
Requires-Dist: puremagic==1.28
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: black==24.10.0; extra == "dev"
|
|
26
|
+
Requires-Dist: build==1.2.2.post1; extra == "dev"
|
|
27
|
+
Requires-Dist: commitizen==3.29.1; extra == "dev"
|
|
28
|
+
Requires-Dist: importlib-resources==6.4.5; extra == "dev"
|
|
29
|
+
Requires-Dist: inflect==7.3.1; extra == "dev"
|
|
30
|
+
Requires-Dist: ipykernel==6.29.5; extra == "dev"
|
|
31
|
+
Requires-Dist: jaraco.collections==5.1.0; extra == "dev"
|
|
32
|
+
Requires-Dist: nbstripout==0.7.1; extra == "dev"
|
|
33
|
+
Requires-Dist: ordered-set==4.1.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pip-autoremove==0.10.0; extra == "dev"
|
|
35
|
+
Requires-Dist: pip-chill==1.0.3; extra == "dev"
|
|
36
|
+
Requires-Dist: pip-upgrade-outdated==1.5; extra == "dev"
|
|
37
|
+
Requires-Dist: pip3-autoremove==1.2.2; extra == "dev"
|
|
38
|
+
Requires-Dist: pre-commit==4.0.1; extra == "dev"
|
|
39
|
+
Requires-Dist: pyright==1.1.386; extra == "dev"
|
|
40
|
+
Requires-Dist: pytest-cov==5.0.0; extra == "dev"
|
|
41
|
+
Requires-Dist: tomli==2.0.2; extra == "dev"
|
|
42
|
+
Requires-Dist: twine==5.1.1; extra == "dev"
|
|
20
43
|
|
|
21
44
|
[](https://github.com/psf/black)
|
|
22
45
|
[](https://microsoft.github.io/pyright/)
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "rudi-node-write"
|
|
7
|
-
version = "1.2.
|
|
7
|
+
version = "1.2.2"
|
|
8
8
|
authors = [{ name = "Olivier Martineau", email = "olivier.martineau@irisa.fr" }]
|
|
9
9
|
maintainers = [{ name = "Olivier Martineau", email = "olivier.martineau@irisa.fr" }]
|
|
10
10
|
description = "Use the internal API of a RUDI Producer node"
|
|
@@ -18,8 +18,8 @@ classifiers = ["Programming Language :: Python :: 3.11",
|
|
|
18
18
|
"License :: OSI Approved :: European Union Public Licence 1.2 (EUPL 1.2)",
|
|
19
19
|
]
|
|
20
20
|
keywords = ["rudi-node-write", "rudi-node-put", "RUDI", "producer node", "RUDI node", "open-data", "Univ. Rennes"]
|
|
21
|
-
dynamic = ["dependencies"]
|
|
22
|
-
# dependencies = ["beautifulsoup4", "chardet", "deepdiff", "
|
|
21
|
+
dynamic = ["dependencies", "optional-dependencies"]
|
|
22
|
+
# dependencies = ["beautifulsoup4", "chardet", "deepdiff", "puremagic"]
|
|
23
23
|
|
|
24
24
|
[project.urls]
|
|
25
25
|
Homepage = "https://github.com/OlivierMartineau/rudi-node-write"
|
|
@@ -34,7 +34,7 @@ target-version = ['py311']
|
|
|
34
34
|
# ----- Tool: commitizen
|
|
35
35
|
[tool.commitizen]
|
|
36
36
|
name = "cz_conventional_commits"
|
|
37
|
-
version = "1.2.
|
|
37
|
+
version = "1.2.2"
|
|
38
38
|
version_files = ["pyproject.toml:version"]
|
|
39
39
|
|
|
40
40
|
# ----- Tool: pytest
|
|
@@ -51,6 +51,7 @@ include = ["rudi_node_write*"]
|
|
|
51
51
|
|
|
52
52
|
[tool.setuptools.dynamic]
|
|
53
53
|
dependencies = {file = ["requirements.txt"]}
|
|
54
|
+
optional-dependencies = {dev = { file = ["requirements-dev.txt"] }}
|
|
54
55
|
|
|
55
56
|
# ----- Tool: pyright
|
|
56
57
|
[tool.pyright]
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
black==24.10.0
|
|
2
|
+
build==1.2.2.post1
|
|
3
|
+
commitizen==3.29.1
|
|
4
|
+
importlib-resources==6.4.5
|
|
5
|
+
inflect==7.3.1
|
|
6
|
+
ipykernel==6.29.5
|
|
7
|
+
jaraco.collections==5.1.0
|
|
8
|
+
nbstripout==0.7.1
|
|
9
|
+
ordered-set==4.1.0
|
|
10
|
+
pip-autoremove==0.10.0
|
|
11
|
+
pip-chill==1.0.3
|
|
12
|
+
pip-upgrade-outdated==1.5
|
|
13
|
+
pip3-autoremove==1.2.2
|
|
14
|
+
pre-commit==4.0.1
|
|
15
|
+
pyright==1.1.386
|
|
16
|
+
pytest-cov==5.0.0
|
|
17
|
+
tomli==2.0.2
|
|
18
|
+
twine==5.1.1
|
|
19
|
+
# appnope==0.1.4 # Installed as dependency for ipykernel
|
|
20
|
+
# argcomplete==3.5.1 # Installed as dependency for commitizen
|
|
21
|
+
# asttokens==2.4.1 # Installed as dependency for stack-data
|
|
22
|
+
# attrs==24.2.0 # Installed as dependency for jsonschema, referencing
|
|
23
|
+
# autocommand==2.2.2 # Installed as dependency for jaraco.text
|
|
24
|
+
# backports.tarfile==1.2.0 # Installed as dependency for jaraco.context
|
|
25
|
+
# certifi==2024.8.30 # Installed as dependency for requests
|
|
26
|
+
# cfgv==3.4.0 # Installed as dependency for pre-commit
|
|
27
|
+
# charset-normalizer==3.4.0 # Installed as dependency for commitizen, requests
|
|
28
|
+
# click==8.1.7 # Installed as dependency for black
|
|
29
|
+
# colorama==0.4.6 # Installed as dependency for commitizen
|
|
30
|
+
# comm==0.2.2 # Installed as dependency for ipykernel
|
|
31
|
+
# coverage==7.6.4 # Installed as dependency for pytest-cov
|
|
32
|
+
# debugpy==1.8.7 # Installed as dependency for ipykernel
|
|
33
|
+
# decli==0.6.2 # Installed as dependency for commitizen
|
|
34
|
+
# decorator==5.1.1 # Installed as dependency for ipython
|
|
35
|
+
# distlib==0.3.9 # Installed as dependency for virtualenv
|
|
36
|
+
# docutils==0.21.2 # Installed as dependency for readme-renderer
|
|
37
|
+
# executing==2.1.0 # Installed as dependency for stack-data
|
|
38
|
+
# fastjsonschema==2.20.0 # Installed as dependency for nbformat
|
|
39
|
+
# filelock==3.16.1 # Installed as dependency for virtualenv
|
|
40
|
+
# identify==2.6.1 # Installed as dependency for pre-commit
|
|
41
|
+
# idna==3.10 # Installed as dependency for requests
|
|
42
|
+
# importlib-metadata==8.5.0 # Installed as dependency for keyring, twine
|
|
43
|
+
# iniconfig==2.0.0 # Installed as dependency for pytest
|
|
44
|
+
# ipython==8.28.0 # Installed as dependency for ipykernel
|
|
45
|
+
# jaraco.classes==3.4.0 # Installed as dependency for keyring
|
|
46
|
+
# jaraco.context==6.0.1 # Installed as dependency for jaraco.text, keyring
|
|
47
|
+
# jaraco.functools==4.1.0 # Installed as dependency for jaraco.text, keyring
|
|
48
|
+
# jaraco.text==4.0.0 # Installed as dependency for jaraco.collections
|
|
49
|
+
# jedi==0.19.1 # Installed as dependency for ipython
|
|
50
|
+
# jinja2==3.1.4 # Installed as dependency for commitizen
|
|
51
|
+
# jsonschema==4.23.0 # Installed as dependency for nbformat
|
|
52
|
+
# jsonschema-specifications==2024.10.1 # Installed as dependency for jsonschema
|
|
53
|
+
# jupyter-client==8.6.3 # Installed as dependency for ipykernel
|
|
54
|
+
# jupyter-core==5.7.2 # Installed as dependency for ipykernel, jupyter-client, nbformat
|
|
55
|
+
# keyring==25.4.1 # Installed as dependency for twine
|
|
56
|
+
# markdown-it-py==3.0.0 # Installed as dependency for rich
|
|
57
|
+
# markupsafe==3.0.2 # Installed as dependency for jinja2
|
|
58
|
+
# matplotlib-inline==0.1.7 # Installed as dependency for ipykernel, ipython
|
|
59
|
+
# mdurl==0.1.2 # Installed as dependency for markdown-it-py
|
|
60
|
+
# more-itertools==10.5.0 # Installed as dependency for inflect, jaraco.classes, jaraco.functools, jaraco.text
|
|
61
|
+
# mypy-extensions==1.0.0 # Installed as dependency for black
|
|
62
|
+
# nbformat==5.10.4 # Installed as dependency for nbstripout
|
|
63
|
+
# nest-asyncio==1.6.0 # Installed as dependency for ipykernel
|
|
64
|
+
# nh3==0.2.18 # Installed as dependency for readme-renderer
|
|
65
|
+
# nodeenv==1.9.1 # Installed as dependency for pre-commit, pyright
|
|
66
|
+
# packaging==24.1 # Installed as dependency for black, build, commitizen, ipykernel, pytest
|
|
67
|
+
# parso==0.8.4 # Installed as dependency for jedi
|
|
68
|
+
# pathspec==0.12.1 # Installed as dependency for black
|
|
69
|
+
# pexpect==4.9.0 # Installed as dependency for ipython
|
|
70
|
+
# pkginfo==1.11.2 # Installed as dependency for twine
|
|
71
|
+
# platformdirs==4.3.6 # Installed as dependency for black, jupyter-core, virtualenv
|
|
72
|
+
# pluggy==1.5.0 # Installed as dependency for pytest
|
|
73
|
+
# prompt-toolkit==3.0.48 # Installed as dependency for ipython, questionary
|
|
74
|
+
# psutil==6.1.0 # Installed as dependency for ipykernel
|
|
75
|
+
# ptyprocess==0.7.0 # Installed as dependency for pexpect
|
|
76
|
+
# pure-eval==0.2.3 # Installed as dependency for stack-data
|
|
77
|
+
# pygments==2.18.0 # Installed as dependency for ipython, readme-renderer, rich
|
|
78
|
+
# pyproject-hooks==1.2.0 # Installed as dependency for build
|
|
79
|
+
# pytest==8.3.3 # Installed as dependency for pytest-cov
|
|
80
|
+
# python-dateutil==2.9.0.post0 # Installed as dependency for jupyter-client
|
|
81
|
+
# pyyaml==6.0.2 # Installed as dependency for commitizen, pre-commit
|
|
82
|
+
# pyzmq==26.2.0 # Installed as dependency for ipykernel, jupyter-client
|
|
83
|
+
# questionary==2.0.1 # Installed as dependency for commitizen
|
|
84
|
+
# readme-renderer==44.0 # Installed as dependency for twine
|
|
85
|
+
# referencing==0.35.1 # Installed as dependency for jsonschema, jsonschema-specifications
|
|
86
|
+
# requests==2.32.3 # Installed as dependency for requests-toolbelt, twine
|
|
87
|
+
# requests-toolbelt==1.0.0 # Installed as dependency for twine
|
|
88
|
+
# rfc3986==2.0.0 # Installed as dependency for twine
|
|
89
|
+
# rich==13.9.3 # Installed as dependency for twine
|
|
90
|
+
# rpds-py==0.20.0 # Installed as dependency for jsonschema, referencing
|
|
91
|
+
# six==1.16.0 # Installed as dependency for asttokens, python-dateutil
|
|
92
|
+
# stack-data==0.6.3 # Installed as dependency for ipython
|
|
93
|
+
# termcolor==2.5.0 # Installed as dependency for commitizen
|
|
94
|
+
# tomlkit==0.13.2 # Installed as dependency for commitizen
|
|
95
|
+
# tornado==6.4.1 # Installed as dependency for ipykernel, jupyter-client
|
|
96
|
+
# traitlets==5.14.3 # Installed as dependency for comm, ipykernel, ipython, jupyter-client, jupyter-core, matplotlib-inline, nbformat
|
|
97
|
+
# typeguard==4.3.0 # Installed as dependency for inflect
|
|
98
|
+
# typing-extensions==4.12.2 # Installed as dependency for ipython, pyright, typeguard
|
|
99
|
+
# urllib3==2.2.3 # Installed as dependency for requests, twine
|
|
100
|
+
# virtualenv==20.27.0 # Installed as dependency for pre-commit
|
|
101
|
+
# wcwidth==0.2.13 # Installed as dependency for prompt-toolkit
|
|
102
|
+
# zipp==3.20.2 # Installed as dependency for importlib-metadata
|
|
@@ -101,16 +101,16 @@ def clean_nones(value):
|
|
|
101
101
|
return value
|
|
102
102
|
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
#
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
#
|
|
115
|
-
#
|
|
116
|
-
#
|
|
104
|
+
if __name__ == "__main__": # pragma: no cover
|
|
105
|
+
tests = "tests"
|
|
106
|
+
# begin = time()
|
|
107
|
+
a = [1, 2, 3, 4, 5]
|
|
108
|
+
b = [9, 8, 7, 6, {"r": [5, 6]}]
|
|
109
|
+
c = [8, 7, 6, {"r": [5, 6]}, 9]
|
|
110
|
+
print(tests, f"{a} Δ {b}", list_diff(a, b))
|
|
111
|
+
print(tests, f"{a} Δ {c}", list_diff(a, c))
|
|
112
|
+
print(tests, f"{b} Δ {c}", list_diff(b, c))
|
|
113
|
+
print(tests, "b == c", are_list_equal(b, c))
|
|
114
|
+
# print(tests, f'{b} == {c} ->', are_list_equal(b, c))
|
|
115
|
+
# print(tests, f'dict eq ->', {'r': [6, 5]} != {'r': [5, 6]})
|
|
116
|
+
# log_d(tests, "exec. time", time() - begin)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: rudi-node-write
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.2
|
|
4
4
|
Summary: Use the internal API of a RUDI Producer node
|
|
5
5
|
Author-email: Olivier Martineau <olivier.martineau@irisa.fr>
|
|
6
6
|
Maintainer-email: Olivier Martineau <olivier.martineau@irisa.fr>
|
|
@@ -17,6 +17,29 @@ Classifier: License :: OSI Approved :: European Union Public Licence 1.2 (EUPL 1
|
|
|
17
17
|
Requires-Python: >=3.11
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
19
|
License-File: LICENCE.md
|
|
20
|
+
Requires-Dist: beautifulsoup4==4.12.3
|
|
21
|
+
Requires-Dist: chardet==5.2.0
|
|
22
|
+
Requires-Dist: deepdiff==8.0.1
|
|
23
|
+
Requires-Dist: puremagic==1.28
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: black==24.10.0; extra == "dev"
|
|
26
|
+
Requires-Dist: build==1.2.2.post1; extra == "dev"
|
|
27
|
+
Requires-Dist: commitizen==3.29.1; extra == "dev"
|
|
28
|
+
Requires-Dist: importlib-resources==6.4.5; extra == "dev"
|
|
29
|
+
Requires-Dist: inflect==7.3.1; extra == "dev"
|
|
30
|
+
Requires-Dist: ipykernel==6.29.5; extra == "dev"
|
|
31
|
+
Requires-Dist: jaraco.collections==5.1.0; extra == "dev"
|
|
32
|
+
Requires-Dist: nbstripout==0.7.1; extra == "dev"
|
|
33
|
+
Requires-Dist: ordered-set==4.1.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pip-autoremove==0.10.0; extra == "dev"
|
|
35
|
+
Requires-Dist: pip-chill==1.0.3; extra == "dev"
|
|
36
|
+
Requires-Dist: pip-upgrade-outdated==1.5; extra == "dev"
|
|
37
|
+
Requires-Dist: pip3-autoremove==1.2.2; extra == "dev"
|
|
38
|
+
Requires-Dist: pre-commit==4.0.1; extra == "dev"
|
|
39
|
+
Requires-Dist: pyright==1.1.386; extra == "dev"
|
|
40
|
+
Requires-Dist: pytest-cov==5.0.0; extra == "dev"
|
|
41
|
+
Requires-Dist: tomli==2.0.2; extra == "dev"
|
|
42
|
+
Requires-Dist: twine==5.1.1; extra == "dev"
|
|
20
43
|
|
|
21
44
|
[](https://github.com/psf/black)
|
|
22
45
|
[](https://microsoft.github.io/pyright/)
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
LICENCE.md
|
|
2
2
|
README.md
|
|
3
3
|
pyproject.toml
|
|
4
|
+
requirements-dev.txt
|
|
4
5
|
requirements.txt
|
|
5
6
|
src/rudi_node_write/__init__.py
|
|
6
7
|
src/rudi_node_write/rudi_node_writer.py
|
|
7
8
|
src/rudi_node_write.egg-info/PKG-INFO
|
|
8
9
|
src/rudi_node_write.egg-info/SOURCES.txt
|
|
9
10
|
src/rudi_node_write.egg-info/dependency_links.txt
|
|
11
|
+
src/rudi_node_write.egg-info/requires.txt
|
|
10
12
|
src/rudi_node_write.egg-info/top_level.txt
|
|
11
13
|
src/rudi_node_write/conf/meta_defaults.py
|
|
12
14
|
src/rudi_node_write/connectors/io_connector.py
|
|
@@ -37,7 +39,4 @@ src/rudi_node_write/utils/str_utils.py
|
|
|
37
39
|
src/rudi_node_write/utils/type_date.py
|
|
38
40
|
src/rudi_node_write/utils/typing_utils.py
|
|
39
41
|
src/rudi_node_write/utils/url_utils.py
|
|
40
|
-
src/rudi_node_write/wip/clean_node.py
|
|
41
|
-
src/rudi_node_write/wip/federation_backup.py
|
|
42
|
-
src/rudi_node_write/wip/rudinode_federation.py
|
|
43
42
|
tests/test_rudi_node_write.py
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
beautifulsoup4==4.12.3
|
|
2
|
+
chardet==5.2.0
|
|
3
|
+
deepdiff==8.0.1
|
|
4
|
+
puremagic==1.28
|
|
5
|
+
|
|
6
|
+
[dev]
|
|
7
|
+
black==24.10.0
|
|
8
|
+
build==1.2.2.post1
|
|
9
|
+
commitizen==3.29.1
|
|
10
|
+
importlib-resources==6.4.5
|
|
11
|
+
inflect==7.3.1
|
|
12
|
+
ipykernel==6.29.5
|
|
13
|
+
jaraco.collections==5.1.0
|
|
14
|
+
nbstripout==0.7.1
|
|
15
|
+
ordered-set==4.1.0
|
|
16
|
+
pip-autoremove==0.10.0
|
|
17
|
+
pip-chill==1.0.3
|
|
18
|
+
pip-upgrade-outdated==1.5
|
|
19
|
+
pip3-autoremove==1.2.2
|
|
20
|
+
pre-commit==4.0.1
|
|
21
|
+
pyright==1.1.386
|
|
22
|
+
pytest-cov==5.0.0
|
|
23
|
+
tomli==2.0.2
|
|
24
|
+
twine==5.1.1
|
|
File without changes
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
from abc import ABC
|
|
2
|
-
from concurrent.futures import as_completed, ThreadPoolExecutor
|
|
3
|
-
from dataclasses import dataclass
|
|
4
|
-
from os import cpu_count
|
|
5
|
-
from time import sleep, time
|
|
6
|
-
from typing import Callable
|
|
7
|
-
from urllib.request import urlopen
|
|
8
|
-
|
|
9
|
-
from rudi_node_write.connectors.io_connector import HTTP_REQUEST_METHODS
|
|
10
|
-
from rudi_node_write.connectors.io_rudi_api_write import RudiNodeApiConnector
|
|
11
|
-
from rudi_node_write.connectors.io_rudi_jwt_factory import RudiNodeJwtFactory
|
|
12
|
-
from rudi_node_write.connectors.io_rudi_manager_write import RudiNodeManagerConnector
|
|
13
|
-
from rudi_node_write.connectors.rudi_node_auth import RudiNodeAuth
|
|
14
|
-
from rudi_node_write.rudi_node_writer import RudiNodeWriter
|
|
15
|
-
from rudi_node_write.utils.file_utils import check_is_dir, check_is_file, read_json_file, write_json_file
|
|
16
|
-
from rudi_node_write.utils.log import log_d, log_e, log_w
|
|
17
|
-
from rudi_node_write.utils.str_utils import slash_join
|
|
18
|
-
from rudi_node_write.utils.type_date import Date
|
|
19
|
-
from rudi_node_write.utils.url_utils import ensure_http, ensure_url_startswith
|
|
20
|
-
|
|
21
|
-
if __name__ == "__main__": # pragma: no cover
|
|
22
|
-
begin = time()
|
|
23
|
-
here = "RudiNodeClean"
|
|
24
|
-
|
|
25
|
-
test_dir = check_is_dir("../dwnld")
|
|
26
|
-
data_dir = check_is_dir("../data")
|
|
27
|
-
creds_file = read_json_file("../creds/creds_release.json")
|
|
28
|
-
auth = RudiNodeAuth(b64url_auth=creds_file["b64auth"])
|
|
29
|
-
node = RudiNodeWriter(creds_file["pm_url"], auth, keep_connection=True)
|
|
30
|
-
|
|
31
|
-
for meta in node.metadata_list:
|
|
32
|
-
changed = False
|
|
33
|
-
print(meta["global_id"], ":", meta["access_condition"]["confidentiality"]["gdpr_sensitive"])
|
|
34
|
-
if meta["access_condition"]["confidentiality"]["gdpr_sensitive"] == None:
|
|
35
|
-
meta["access_condition"]["confidentiality"]["gdpr_sensitive"] = False
|
|
36
|
-
changed = True
|
|
37
|
-
# try:
|
|
38
|
-
# if meta["geography"]["geographic_distribution"]["geometry"] == None:
|
|
39
|
-
# del meta["geography"]["geographic_distribution"]["geometry"]
|
|
40
|
-
# changed = True
|
|
41
|
-
# except:
|
|
42
|
-
# pass
|
|
43
|
-
# try:
|
|
44
|
-
# if meta["metadata_info"]["metadata_dates"]["published"] == None:
|
|
45
|
-
# del meta["metadata_info"]["metadata_dates"]["published"]
|
|
46
|
-
# changed = True
|
|
47
|
-
# except:
|
|
48
|
-
# pass
|
|
49
|
-
if changed:
|
|
50
|
-
node.put_metadata(meta)
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
from concurrent.futures import as_completed, ThreadPoolExecutor
|
|
2
|
-
from os import cpu_count
|
|
3
|
-
from time import sleep, time
|
|
4
|
-
from urllib.request import urlopen
|
|
5
|
-
|
|
6
|
-
from rudi_node_write.connectors.io_rudi_manager_write import RudiNodeManagerConnector
|
|
7
|
-
from rudi_node_write.connectors.rudi_node_auth import RudiNodeAuth
|
|
8
|
-
from rudi_node_write.rudi_node_writer import RudiNodeWriter
|
|
9
|
-
from rudi_node_write.utils.file_utils import check_is_dir, check_is_file, read_json_file, write_json_file
|
|
10
|
-
from rudi_node_write.utils.log import log_d, log_e, log_w
|
|
11
|
-
from rudi_node_write.utils.str_utils import slash_join
|
|
12
|
-
from rudi_node_write.utils.type_date import Date
|
|
13
|
-
|
|
14
|
-
federation_data = {}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
MAX_WORKERS = 0
|
|
18
|
-
DEFAULT_WAIT_TIME = 0.3
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def try_request(req, wait_time=DEFAULT_WAIT_TIME, quit_on_fail=True):
|
|
22
|
-
fun = "try_request"
|
|
23
|
-
sleep(wait_time)
|
|
24
|
-
try:
|
|
25
|
-
return req
|
|
26
|
-
except Exception as err:
|
|
27
|
-
if quit_on_fail:
|
|
28
|
-
return "FAIL"
|
|
29
|
-
# Let's try one more time
|
|
30
|
-
return try_request(req, wait_time, True)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def backup_node(node_name, node_info):
|
|
34
|
-
node_url = node_info["url"]
|
|
35
|
-
pm_url = node_info["pmback"] if node_info.get("pmback") is not None else (slash_join(node_url, "prodmanager"))
|
|
36
|
-
if not pm_url.startswith("http"):
|
|
37
|
-
pm_url = "https://" + pm_url
|
|
38
|
-
|
|
39
|
-
node = RudiNodeWriter(pm_url=pm_url, auth=auth, keep_connection=True)
|
|
40
|
-
|
|
41
|
-
node_data = {"node_name": node_name, "pm_url": node.pm_url}
|
|
42
|
-
node_data["media_url"] = try_request(node.media_url)
|
|
43
|
-
node_data["init_data"] = try_request(node.init_data)
|
|
44
|
-
node_data["organization_list"] = try_request(node.organization_list)
|
|
45
|
-
node_data["contact_list"] = try_request(node.contact_list)
|
|
46
|
-
node_data["metadata_list"] = try_request(node.metadata_list)
|
|
47
|
-
node_data["enums"] = try_request(node.enums)
|
|
48
|
-
node_data["media_list"] = try_request(node.media_list)
|
|
49
|
-
|
|
50
|
-
node.close_connection()
|
|
51
|
-
return node_data
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if __name__ == "__main__": # pragma: no cover
|
|
55
|
-
begin = time()
|
|
56
|
-
here = "RudiNodeFederation backup"
|
|
57
|
-
|
|
58
|
-
test_dir = check_is_dir("../dwnld")
|
|
59
|
-
data_dir = check_is_dir("../data")
|
|
60
|
-
creds_file = check_is_file("../creds/test_creds_manager.json")
|
|
61
|
-
servers_file = check_is_file("../creds/servers.json")
|
|
62
|
-
|
|
63
|
-
servers_list = read_json_file(servers_file)
|
|
64
|
-
nodes = servers_list.get("nodes")
|
|
65
|
-
|
|
66
|
-
# nodes = {"exatow": nodes["exatow"]}
|
|
67
|
-
|
|
68
|
-
nb_nodes = len(nodes.keys())
|
|
69
|
-
|
|
70
|
-
rudi_node_creds = read_json_file(creds_file)
|
|
71
|
-
auth = RudiNodeAuth.from_json(rudi_node_creds)
|
|
72
|
-
url = rudi_node_creds["url"]
|
|
73
|
-
pm_url = url if url.endswith("prodmanager") else slash_join(url, "prodmanager")
|
|
74
|
-
assert isinstance(auth, RudiNodeAuth)
|
|
75
|
-
errors = {}
|
|
76
|
-
if MAX_WORKERS:
|
|
77
|
-
with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
|
|
78
|
-
futures = {executor.submit(backup_node, node_name, nodes[node_name]): node_name for node_name in nodes}
|
|
79
|
-
for future in as_completed(futures, timeout=120):
|
|
80
|
-
try:
|
|
81
|
-
future_result = future.result()
|
|
82
|
-
except Exception as err:
|
|
83
|
-
node_name = futures[future]
|
|
84
|
-
log_e(here, "Backup failed for node:", futures[future])
|
|
85
|
-
future_result = {}
|
|
86
|
-
errors[node_name] = err
|
|
87
|
-
node_name = futures[future]
|
|
88
|
-
future_result["node_name"] = None
|
|
89
|
-
federation_data[node_name] = future_result
|
|
90
|
-
else:
|
|
91
|
-
# federation_info = {nodes[node_name] for node_name in nodes}
|
|
92
|
-
|
|
93
|
-
for node_name in nodes:
|
|
94
|
-
log_d(here, "----- node_name", node_name)
|
|
95
|
-
node_info = nodes[node_name]
|
|
96
|
-
try:
|
|
97
|
-
node_data = backup_node(node_name, node_info)
|
|
98
|
-
federation_data[node_name] = node_data
|
|
99
|
-
|
|
100
|
-
write_json_file(destination_file_path=slash_join(data_dir, node_name + ".json"), json_dict=node_data)
|
|
101
|
-
except Exception as e:
|
|
102
|
-
errors[node_name] = e
|
|
103
|
-
node_data = None
|
|
104
|
-
|
|
105
|
-
federation_data[node_name] = node_data
|
|
106
|
-
|
|
107
|
-
write_json_file(destination_file_path=slash_join(data_dir, "_federation.json"), json_dict=federation_data)
|
|
108
|
-
if len(errors.keys()) > 0:
|
|
109
|
-
log_e(here, "Backup failed for some nodes:", errors)
|
|
110
|
-
else:
|
|
111
|
-
log_d(here, "All nodes were successfully backed up")
|
|
112
|
-
|
|
113
|
-
log_d(here, "exec. time", time() - begin)
|
|
114
|
-
|
|
115
|
-
# urls = [
|
|
116
|
-
# # "http://www.foxnews.com/",
|
|
117
|
-
# "http://www.cnn.com/",
|
|
118
|
-
# "http://europe.wsj.com/",
|
|
119
|
-
# "http://www.bbc.co.uk/",
|
|
120
|
-
# "http://some-made-up-domain.com/",
|
|
121
|
-
# ]
|
|
122
|
-
|
|
123
|
-
# url_dict = {url + "r": url for url in urls}
|
|
124
|
-
# print(url_dict)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
# def load_url(url, timeout):
|
|
128
|
-
# with urlopen(url, timeout=timeout) as conn:
|
|
129
|
-
# return conn.read()
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
# with ThreadPoolExecutor(max_workers=5) as executor:
|
|
133
|
-
# future_to_url = {executor.submit(load_url, url, 60): url for url in urls}
|
|
134
|
-
# for future in as_completed(future_to_url):
|
|
135
|
-
# url = future_to_url[future]
|
|
136
|
-
# try:
|
|
137
|
-
# data = future.result()
|
|
138
|
-
# except Exception as exc:
|
|
139
|
-
# print("%r generated an exception: %s" % (url, exc))
|
|
140
|
-
# else:
|
|
141
|
-
# print("%r page is %d bytes" % (url, len(data)))
|
|
142
|
-
|
|
143
|
-
# print(cpu_count() * 5)
|
|
144
|
-
# pool = ThreadPoolExecutor()
|
|
145
|
-
# print(pool._max_workers)
|
|
@@ -1,412 +0,0 @@
|
|
|
1
|
-
from abc import ABC
|
|
2
|
-
from concurrent.futures import as_completed, ThreadPoolExecutor
|
|
3
|
-
from dataclasses import dataclass
|
|
4
|
-
from os import cpu_count
|
|
5
|
-
from time import sleep, time
|
|
6
|
-
from typing import Callable
|
|
7
|
-
from urllib.request import urlopen
|
|
8
|
-
|
|
9
|
-
from rudi_node_write.connectors.io_connector import HTTP_REQUEST_METHODS
|
|
10
|
-
from rudi_node_write.connectors.io_rudi_api_write import RudiNodeApiConnector
|
|
11
|
-
from rudi_node_write.connectors.io_rudi_jwt_factory import RudiNodeJwtFactory
|
|
12
|
-
from rudi_node_write.connectors.io_rudi_manager_write import RudiNodeManagerConnector
|
|
13
|
-
from rudi_node_write.connectors.rudi_node_auth import RudiNodeAuth
|
|
14
|
-
from rudi_node_write.rudi_node_writer import RudiNodeWriter
|
|
15
|
-
from rudi_node_write.utils.file_utils import check_is_dir, check_is_file, read_json_file, write_json_file
|
|
16
|
-
from rudi_node_write.utils.log import log_d, log_e, log_w
|
|
17
|
-
from rudi_node_write.utils.str_utils import slash_join
|
|
18
|
-
from rudi_node_write.utils.type_date import Date
|
|
19
|
-
from rudi_node_write.utils.url_utils import ensure_http, ensure_url_startswith
|
|
20
|
-
|
|
21
|
-
federation_data = {}
|
|
22
|
-
|
|
23
|
-
DEFAULT_WAIT_TIME = 0.3
|
|
24
|
-
|
|
25
|
-
NO_PORTAL = "No portal connected"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def ensure_url_startswith_api(url):
|
|
29
|
-
return ensure_url_startswith(url, "api")
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
class Module:
|
|
33
|
-
MANAGER = "manager"
|
|
34
|
-
CATALOG = "catalog"
|
|
35
|
-
STORAGE = "storage"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
class HttpMethods:
|
|
39
|
-
GET = "GET"
|
|
40
|
-
POST = "POST"
|
|
41
|
-
PUT = "PUT"
|
|
42
|
-
DELETE = "DELETE"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
@dataclass
|
|
46
|
-
class ModuleRequest:
|
|
47
|
-
action_name: str
|
|
48
|
-
module_name: Module = Module.MANAGER
|
|
49
|
-
req_method: HttpMethods = HttpMethods.GET
|
|
50
|
-
url_bit: str = "/"
|
|
51
|
-
post_treatment: Callable = lambda x: x
|
|
52
|
-
can_fail: bool = False
|
|
53
|
-
keep_alive: bool = False
|
|
54
|
-
should_log_request: bool = False
|
|
55
|
-
should_log_response: bool = False
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
# TODO: envoyer une suite/liste de traitements sur les nœuds:
|
|
59
|
-
# - quel connecteur cible (node_write ? catalog ? media ?)
|
|
60
|
-
# - quelle URL requête (url_bit )
|
|
61
|
-
# - quel post-traitement
|
|
62
|
-
#
|
|
63
|
-
# => Input: objet à définir
|
|
64
|
-
# #
|
|
65
|
-
# [{
|
|
66
|
-
# target: Module.MANAGER | Module.CATALOG | MEDIA,
|
|
67
|
-
# url_bit,
|
|
68
|
-
# post_treatment on answer (defaulted to x=>x)
|
|
69
|
-
# opts: keep_alive, log request, log response (defaulted to False)
|
|
70
|
-
# }]
|
|
71
|
-
class NodeConnector:
|
|
72
|
-
def __init__(
|
|
73
|
-
self,
|
|
74
|
-
node_name,
|
|
75
|
-
catalog_url,
|
|
76
|
-
catalog_auth,
|
|
77
|
-
manager_url,
|
|
78
|
-
manager_auth,
|
|
79
|
-
):
|
|
80
|
-
self._node_name = node_name
|
|
81
|
-
self._catalog = CatalogConnector(node_name=node_name, module_url=catalog_url, module_auth=catalog_auth)
|
|
82
|
-
self._manager = ManagerConnector(node_name=node_name, module_url=manager_url, module_auth=manager_auth)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
class ModuleConnector(ABC):
|
|
86
|
-
def __init__(self, node_name: str, get_connector: Callable, get_headers: Callable):
|
|
87
|
-
self._node_name = node_name
|
|
88
|
-
self._get_connector = get_connector
|
|
89
|
-
self._get_headers = get_headers
|
|
90
|
-
|
|
91
|
-
@property
|
|
92
|
-
def node_name(self):
|
|
93
|
-
return self._node_name
|
|
94
|
-
|
|
95
|
-
@property
|
|
96
|
-
def module_name(self):
|
|
97
|
-
raise NotImplementedError("This function should be implemented")
|
|
98
|
-
|
|
99
|
-
@property
|
|
100
|
-
def connector(self):
|
|
101
|
-
return self._get_connector()
|
|
102
|
-
|
|
103
|
-
@property
|
|
104
|
-
def headers(self):
|
|
105
|
-
return self._get_headers()
|
|
106
|
-
|
|
107
|
-
@staticmethod
|
|
108
|
-
def create_connector(node_name, module_name, module_url, module_auth):
|
|
109
|
-
if module_name == Module.MANAGER:
|
|
110
|
-
return ManagerConnector(node_name=node_name, module_url=module_url, module_auth=module_auth)
|
|
111
|
-
if module_name == Module.CATALOG:
|
|
112
|
-
return CatalogConnector(node_name=node_name, module_url=module_url, module_auth=module_auth)
|
|
113
|
-
|
|
114
|
-
def module_request(
|
|
115
|
-
self,
|
|
116
|
-
request: ModuleRequest,
|
|
117
|
-
):
|
|
118
|
-
return self.request(
|
|
119
|
-
req_method=request.req_method,
|
|
120
|
-
url_bit=request.url_bit,
|
|
121
|
-
post_treatment=request.post_treatment,
|
|
122
|
-
can_fail=request.can_fail,
|
|
123
|
-
keep_alive=request.keep_alive,
|
|
124
|
-
should_log_request=request.should_log_request,
|
|
125
|
-
should_log_response=request.should_log_response,
|
|
126
|
-
)
|
|
127
|
-
|
|
128
|
-
def request(
|
|
129
|
-
self,
|
|
130
|
-
req_method: HttpMethods,
|
|
131
|
-
url_bit: str,
|
|
132
|
-
post_treatment=lambda x: x,
|
|
133
|
-
can_fail: bool = False,
|
|
134
|
-
keep_alive: bool = False,
|
|
135
|
-
should_log_request: bool = False,
|
|
136
|
-
should_log_response: bool = False,
|
|
137
|
-
):
|
|
138
|
-
try:
|
|
139
|
-
node_res = self.connector.request(
|
|
140
|
-
req_method=req_method,
|
|
141
|
-
relative_url=ensure_url_startswith_api(url_bit),
|
|
142
|
-
headers=self.headers,
|
|
143
|
-
keep_alive=keep_alive,
|
|
144
|
-
should_log_request=should_log_request,
|
|
145
|
-
should_log_response=should_log_response,
|
|
146
|
-
)
|
|
147
|
-
return post_treatment(node_res)
|
|
148
|
-
except Exception as err:
|
|
149
|
-
if can_fail:
|
|
150
|
-
raise err
|
|
151
|
-
return f"ERR: {err}"
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
class ManagerConnector(ModuleConnector):
|
|
155
|
-
def __init__(self, node_name, module_url, module_auth):
|
|
156
|
-
self._node_name = node_name
|
|
157
|
-
self._node_writer = RudiNodeWriter(pm_url=module_url, auth=module_auth, headers_user_agent="ManagerConnector")
|
|
158
|
-
super().__init__(
|
|
159
|
-
node_name=node_name,
|
|
160
|
-
get_connector=lambda: self._node_writer._pm_connector,
|
|
161
|
-
get_headers=lambda: self._node_writer._pm_connector._pm_headers,
|
|
162
|
-
)
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
class CatalogConnector(ModuleConnector):
|
|
166
|
-
def __init__(self, node_name, module_url, module_auth):
|
|
167
|
-
self._node_name = node_name
|
|
168
|
-
self._catalog_connector = RudiNodeApiConnector(
|
|
169
|
-
server_url=module_url, jwt_factory=module_auth, headers_user_agent="CatalogConnector"
|
|
170
|
-
)
|
|
171
|
-
super().__init__(
|
|
172
|
-
node_name=node_name,
|
|
173
|
-
get_connector=lambda: self._catalog_connector,
|
|
174
|
-
get_headers=lambda: self._catalog_connector._headers,
|
|
175
|
-
)
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
class RudiNodeFederation:
|
|
179
|
-
def __init__(self, config_file_path, credentials_file_path, local_jwt_factory):
|
|
180
|
-
self.jwt_factory = local_jwt_factory
|
|
181
|
-
self.load_federation_conf(config_file_path, credentials_file_path)
|
|
182
|
-
|
|
183
|
-
def load_federation_conf(self, config_file_path, credentials_file_path):
|
|
184
|
-
self._conf = read_json_file(config_file_path)
|
|
185
|
-
self._creds = read_json_file(credentials_file_path)
|
|
186
|
-
self._connectors = {}
|
|
187
|
-
|
|
188
|
-
# self._conf["nodes"] = {"exatow": self._conf["nodes"]["exatow"], "rm": self._conf["nodes"]["rm"]}
|
|
189
|
-
|
|
190
|
-
for node_name, node_conf in self.nodes_conf.items():
|
|
191
|
-
print(node_name)
|
|
192
|
-
node_url = ensure_http(node_conf["url"])
|
|
193
|
-
|
|
194
|
-
pm_url = ensure_http(
|
|
195
|
-
node_conf["pmback"] if node_conf.get("pmback") is not None else slash_join(node_url, "prodmanager")
|
|
196
|
-
)
|
|
197
|
-
|
|
198
|
-
self._connectors[node_name] = {
|
|
199
|
-
Module.MANAGER: ManagerConnector(
|
|
200
|
-
node_name=node_name,
|
|
201
|
-
module_url=pm_url,
|
|
202
|
-
module_auth=RudiNodeAuth(b64url_auth=self.get_creds(node_name).get("b64auth")),
|
|
203
|
-
),
|
|
204
|
-
Module.CATALOG: CatalogConnector(
|
|
205
|
-
node_name=node_name, module_url=node_url, module_auth=self.jwt_factory
|
|
206
|
-
),
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
@property
|
|
210
|
-
def nodes_conf(self):
|
|
211
|
-
return self.get_node_conf()
|
|
212
|
-
|
|
213
|
-
def get_node_conf(self, node_name=None):
|
|
214
|
-
if node_name is None:
|
|
215
|
-
return self._conf["nodes"]
|
|
216
|
-
return self._conf["nodes"].get(node_name)
|
|
217
|
-
|
|
218
|
-
def get_creds(self, node_name):
|
|
219
|
-
if self._creds.get(node_name):
|
|
220
|
-
return self._creds[node_name]
|
|
221
|
-
return self._creds["defaults"]
|
|
222
|
-
|
|
223
|
-
def request(
|
|
224
|
-
self,
|
|
225
|
-
node_name,
|
|
226
|
-
module_name,
|
|
227
|
-
req_method,
|
|
228
|
-
url_bit,
|
|
229
|
-
post_treatment=lambda x: x,
|
|
230
|
-
can_fail=False,
|
|
231
|
-
keep_alive=False,
|
|
232
|
-
should_log_request=False,
|
|
233
|
-
should_log_response=False,
|
|
234
|
-
):
|
|
235
|
-
if module_name == Module.MANAGER:
|
|
236
|
-
connector = self._managers[node_name]
|
|
237
|
-
headers = connector._pm_headers
|
|
238
|
-
url_bit = ensure_url_startswith_api(url_bit)
|
|
239
|
-
elif module_name == Module.CATALOG:
|
|
240
|
-
connector = self._catalogs[node_name]
|
|
241
|
-
headers = connector._headers
|
|
242
|
-
url_bit = ensure_url_startswith_api(url_bit)
|
|
243
|
-
else:
|
|
244
|
-
raise NotImplementedError("Not yet available")
|
|
245
|
-
try:
|
|
246
|
-
node_res = connector.request(
|
|
247
|
-
req_method=req_method,
|
|
248
|
-
relative_url=url_bit,
|
|
249
|
-
headers=headers,
|
|
250
|
-
keep_alive=keep_alive,
|
|
251
|
-
should_log_request=should_log_request,
|
|
252
|
-
should_log_response=should_log_response,
|
|
253
|
-
)
|
|
254
|
-
return post_treatment(node_res)
|
|
255
|
-
except Exception as err:
|
|
256
|
-
if can_fail:
|
|
257
|
-
raise err
|
|
258
|
-
return f"ERR: {err}"
|
|
259
|
-
|
|
260
|
-
def batch_request_node(self, connectors, request_list, max_workers=0):
|
|
261
|
-
res = {}
|
|
262
|
-
err = {}
|
|
263
|
-
for request in request_list:
|
|
264
|
-
if isinstance(request, ModuleRequest):
|
|
265
|
-
res[request.action_name] = connectors[request.module_name].module_request(request)
|
|
266
|
-
else:
|
|
267
|
-
(action_name, module_name, req_method, url_bit, post_treatment) = request
|
|
268
|
-
res[action_name] = connectors[module_name].request(
|
|
269
|
-
req_method=req_method,
|
|
270
|
-
url_bit=url_bit,
|
|
271
|
-
post_treatment=post_treatment,
|
|
272
|
-
)
|
|
273
|
-
return res
|
|
274
|
-
|
|
275
|
-
def batch_requests(self, request_list, max_workers=0):
|
|
276
|
-
"""
|
|
277
|
-
@param request_dict: a dict with module names as keys and a list of actions {action_name: (module_name, req_method , url_bit , post_treatment)}}
|
|
278
|
-
"""
|
|
279
|
-
res = {}
|
|
280
|
-
err = {}
|
|
281
|
-
if not max_workers:
|
|
282
|
-
for node_name, connectors in self._connectors.items():
|
|
283
|
-
res[node_name] = self.batch_request_node(connectors, request_list)
|
|
284
|
-
else:
|
|
285
|
-
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
|
286
|
-
futures = {
|
|
287
|
-
executor.submit(connectors[request.module_name].module_request, request): request
|
|
288
|
-
for request in request_list
|
|
289
|
-
}
|
|
290
|
-
for future in as_completed(futures, timeout=120):
|
|
291
|
-
try:
|
|
292
|
-
future_result = future.result()
|
|
293
|
-
except Exception as err:
|
|
294
|
-
node_name = futures[future]
|
|
295
|
-
log_e(here, "Request failed:", futures[future])
|
|
296
|
-
future_result = {}
|
|
297
|
-
errors[request.node_name] = err
|
|
298
|
-
node_name = futures[future]
|
|
299
|
-
future_result["node_name"] = None
|
|
300
|
-
federation_data[node_name] = future_result
|
|
301
|
-
return res
|
|
302
|
-
|
|
303
|
-
def try_request(req, wait_time=DEFAULT_WAIT_TIME, quit_on_fail=True):
|
|
304
|
-
fun = "try_request"
|
|
305
|
-
sleep(wait_time)
|
|
306
|
-
try:
|
|
307
|
-
return req
|
|
308
|
-
except Exception as err:
|
|
309
|
-
if quit_on_fail:
|
|
310
|
-
return "FAIL"
|
|
311
|
-
# Let's try one more time
|
|
312
|
-
return try_request(req, wait_time, True)
|
|
313
|
-
|
|
314
|
-
def backup_node(node_name, node_info):
|
|
315
|
-
node_url = node_info["url"]
|
|
316
|
-
pm_url = node_info["pmback"] if node_info.get("pmback") is not None else (slash_join(node_url, "prodmanager"))
|
|
317
|
-
ensure_http(pm_url)
|
|
318
|
-
|
|
319
|
-
node = RudiNodeWriter(pm_url=pm_url, auth=auth, keep_connection=True)
|
|
320
|
-
|
|
321
|
-
node_data = {"node_name": node_name, "pm_url": node.pm_url}
|
|
322
|
-
node_data["media_url"] = try_request(node.media_url)
|
|
323
|
-
node_data["init_data"] = try_request(node.init_data)
|
|
324
|
-
node_data["organization_list"] = try_request(node.organization_list)
|
|
325
|
-
node_data["contact_list"] = try_request(node.contact_list)
|
|
326
|
-
node_data["metadata_list"] = try_request(node.metadata_list)
|
|
327
|
-
node_data["enums"] = try_request(node.enums)
|
|
328
|
-
node_data["media_list"] = try_request(node.media_list)
|
|
329
|
-
|
|
330
|
-
node.close_connection()
|
|
331
|
-
return node_data
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
if __name__ == "__main__": # pragma: no cover
|
|
335
|
-
begin = time()
|
|
336
|
-
here = "RudiNodeFederation"
|
|
337
|
-
|
|
338
|
-
test_dir = check_is_dir("../dwnld")
|
|
339
|
-
data_dir = check_is_dir("../data")
|
|
340
|
-
creds_file = check_is_file("../creds/federation_creds.json")
|
|
341
|
-
servers_file = check_is_file("../creds/servers.json")
|
|
342
|
-
|
|
343
|
-
try:
|
|
344
|
-
local_jwt_factory = RudiNodeJwtFactory("http://localhost:4040", {"sub": "rudi_api_pm"})
|
|
345
|
-
except:
|
|
346
|
-
raise ConnectionError("Local crypto module is apparently not launched!")
|
|
347
|
-
|
|
348
|
-
rudi_federation = RudiNodeFederation(
|
|
349
|
-
config_file_path=servers_file, credentials_file_path=creds_file, local_jwt_factory=local_jwt_factory
|
|
350
|
-
)
|
|
351
|
-
|
|
352
|
-
def get_token(x):
|
|
353
|
-
if x == NO_PORTAL:
|
|
354
|
-
return NO_PORTAL
|
|
355
|
-
try:
|
|
356
|
-
return x["access_token"].replace(r"[\w-]+(\.[\w-]+){2}", "valid_jwt")
|
|
357
|
-
except:
|
|
358
|
-
return x
|
|
359
|
-
|
|
360
|
-
res = rudi_federation.batch_requests(
|
|
361
|
-
[
|
|
362
|
-
ModuleRequest(
|
|
363
|
-
action_name="portal_url",
|
|
364
|
-
module_name=Module.MANAGER,
|
|
365
|
-
url_bit="front/portal-url",
|
|
366
|
-
can_fail=True,
|
|
367
|
-
should_log_request=True,
|
|
368
|
-
),
|
|
369
|
-
ModuleRequest(
|
|
370
|
-
action_name="portal_token",
|
|
371
|
-
module_name=Module.CATALOG,
|
|
372
|
-
url_bit="admin/portal/token",
|
|
373
|
-
post_treatment=get_token,
|
|
374
|
-
),
|
|
375
|
-
]
|
|
376
|
-
)
|
|
377
|
-
portal_connections_file = "rudi_node_write/wip/portal_connect.json"
|
|
378
|
-
reworked_portal_connect_file = "rudi_node_write/wip/portal_connect_final.json"
|
|
379
|
-
# res = read_json_file("rudi_node_write/wip/portal_connect.json")
|
|
380
|
-
print(res)
|
|
381
|
-
write_json_file(destination_file_path=portal_connections_file, json_dict=res)
|
|
382
|
-
final_res = {}
|
|
383
|
-
for node_name, node_res in res.items():
|
|
384
|
-
portal_url = node_res["portal_url"]
|
|
385
|
-
print(portal_url)
|
|
386
|
-
portal_connection = (
|
|
387
|
-
node_res["portal_token"]
|
|
388
|
-
if not node_res["portal_token"].startswith("eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9")
|
|
389
|
-
else "OK"
|
|
390
|
-
)
|
|
391
|
-
if final_res.get(portal_url) is None:
|
|
392
|
-
final_res[portal_url] = {node_name: portal_connection}
|
|
393
|
-
final_res[portal_url][node_name] = portal_connection
|
|
394
|
-
# print(res)
|
|
395
|
-
# portal_urls = rudi_federation.manager_get("front/portal-url")
|
|
396
|
-
# node_catalog_url = rudi_federation.manager_get("front/ext-api-url")
|
|
397
|
-
# catalog_portal_token = rudi_federation.catalog_get("portal/token", extract_token_from_http_res)
|
|
398
|
-
# node_portals = {}
|
|
399
|
-
# for node_name, portal_url in portal_urls.items():
|
|
400
|
-
# node_info = {"catalog_url": node_catalog_url[node_name], "portal_token": catalog_portal_token}
|
|
401
|
-
# if node_portals.get(portal_url) is None:
|
|
402
|
-
# node_portals[portal_url] = {node_name: node_info}
|
|
403
|
-
# else:
|
|
404
|
-
# node_portals[portal_url][node_name] = node_info
|
|
405
|
-
|
|
406
|
-
# print(node_portals)
|
|
407
|
-
print(final_res)
|
|
408
|
-
write_json_file(destination_file_path=reworked_portal_connect_file, json_dict=final_res)
|
|
409
|
-
|
|
410
|
-
print()
|
|
411
|
-
|
|
412
|
-
# print(chr(sum(range(ord(min(str(not ())))))))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/connectors/io_connector.py
RENAMED
|
File without changes
|
{rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/connectors/io_rudi_api_write.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/connectors/rudi_node_auth.py
RENAMED
|
File without changes
|
|
File without changes
|
{rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/rudi_types/rudi_const.py
RENAMED
|
File without changes
|
{rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/rudi_types/rudi_contact.py
RENAMED
|
File without changes
|
{rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/rudi_types/rudi_dates.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/rudi_types/rudi_licence.py
RENAMED
|
File without changes
|
{rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/rudi_types/rudi_media.py
RENAMED
|
File without changes
|
|
File without changes
|
{rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/rudi_types/rudi_meta_misc.py
RENAMED
|
File without changes
|
|
File without changes
|
{rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write/rudi_types/serializable.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rudi_node_write-1.2.1 → rudi_node_write-1.2.2}/src/rudi_node_write.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|