rudi-node-write 1.2.2__tar.gz → 1.3.0__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.
Files changed (49) hide show
  1. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/PKG-INFO +24 -17
  2. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/README.md +1 -1
  3. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/pyproject.toml +30 -14
  4. rudi_node_write-1.3.0/requirements-dev.txt +112 -0
  5. rudi_node_write-1.3.0/requirements.txt +7 -0
  6. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/connectors/io_connector.py +63 -37
  7. rudi_node_write-1.2.2/src/rudi_node_write/connectors/io_rudi_api_write.py → rudi_node_write-1.3.0/src/rudi_node_write/connectors/io_rudi_catalog_write.py +20 -24
  8. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/connectors/io_rudi_jwt_factory.py +1 -1
  9. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/connectors/io_rudi_manager_write.py +151 -113
  10. rudi_node_write-1.3.0/src/rudi_node_write/connectors/io_rudi_manager_write_v2.py +122 -0
  11. rudi_node_write-1.3.0/src/rudi_node_write/connectors/io_rudi_manager_write_v3.py +1414 -0
  12. rudi_node_write-1.2.2/src/rudi_node_write/connectors/io_rudi_media_write.py → rudi_node_write-1.3.0/src/rudi_node_write/connectors/io_rudi_storage_write.py +4 -4
  13. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/rudi_node_writer.py +75 -23
  14. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/rudi_types/rudi_const.py +3 -0
  15. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/rudi_types/rudi_dictionary_entry.py +1 -1
  16. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/rudi_types/rudi_media.py +2 -1
  17. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/rudi_types/rudi_meta.py +8 -0
  18. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/utils/err.py +5 -4
  19. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/utils/file_utils.py +23 -3
  20. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/utils/list_utils.py +2 -4
  21. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/utils/str_utils.py +1 -1
  22. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write.egg-info/PKG-INFO +24 -17
  23. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write.egg-info/SOURCES.txt +4 -2
  24. rudi_node_write-1.3.0/src/rudi_node_write.egg-info/requires.txt +31 -0
  25. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/tests/test_rudi_node_write.py +5 -8
  26. rudi_node_write-1.2.2/requirements-dev.txt +0 -102
  27. rudi_node_write-1.2.2/requirements.txt +0 -6
  28. rudi_node_write-1.2.2/src/rudi_node_write.egg-info/requires.txt +0 -24
  29. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/LICENCE.md +0 -0
  30. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/setup.cfg +0 -0
  31. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/__init__.py +0 -0
  32. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/conf/meta_defaults.py +0 -0
  33. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/connectors/rudi_node_auth.py +0 -0
  34. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/rudi_types/rudi_contact.py +0 -0
  35. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/rudi_types/rudi_dates.py +0 -0
  36. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/rudi_types/rudi_geo.py +0 -0
  37. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/rudi_types/rudi_licence.py +0 -0
  38. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/rudi_types/rudi_meta_misc.py +0 -0
  39. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/rudi_types/rudi_org.py +0 -0
  40. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/rudi_types/serializable.py +0 -0
  41. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/utils/dict_utils.py +0 -0
  42. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/utils/html_utils.py +0 -0
  43. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/utils/jwt.py +0 -0
  44. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/utils/log.py +0 -0
  45. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/utils/type_date.py +0 -0
  46. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/utils/typing_utils.py +0 -0
  47. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write/utils/url_utils.py +0 -0
  48. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write.egg-info/dependency_links.txt +0 -0
  49. {rudi_node_write-1.2.2 → rudi_node_write-1.3.0}/src/rudi_node_write.egg-info/top_level.txt +0 -0
@@ -1,10 +1,10 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: rudi-node-write
3
- Version: 1.2.2
3
+ Version: 1.3.0
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>
7
- License: EUPL-1.2
7
+ License-Expression: EUPL-1.2
8
8
  Project-URL: Homepage, https://github.com/OlivierMartineau/rudi-node-write
9
9
  Project-URL: Documentation, https://app.swaggerhub.com/apis/OlivierMartineau/RudiProducer-InternalAPI
10
10
  Project-URL: Repository, https://github.com/OlivierMartineau/rudi-node-write
@@ -13,33 +13,40 @@ Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
14
  Classifier: Natural Language :: English
15
15
  Classifier: Operating System :: OS Independent
16
- Classifier: License :: OSI Approved :: European Union Public Licence 1.2 (EUPL 1.2)
17
16
  Requires-Python: >=3.11
18
17
  Description-Content-Type: text/markdown
19
18
  License-File: LICENCE.md
20
- Requires-Dist: beautifulsoup4==4.12.3
19
+ Requires-Dist: beautifulsoup4==4.13.4
21
20
  Requires-Dist: chardet==5.2.0
22
- Requires-Dist: deepdiff==8.0.1
21
+ Requires-Dist: deepdiff==8.4.2
23
22
  Requires-Dist: puremagic==1.28
24
23
  Provides-Extra: dev
25
- Requires-Dist: black==24.10.0; extra == "dev"
24
+ Requires-Dist: backports.tarfile==1.2.0; extra == "dev"
25
+ Requires-Dist: black==25.1.0; extra == "dev"
26
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"
27
+ Requires-Dist: commitizen==4.6.0; extra == "dev"
28
+ Requires-Dist: flake8==7.2.0; extra == "dev"
29
+ Requires-Dist: importlib-metadata==8.6.1; extra == "dev"
30
+ Requires-Dist: importlib-resources==6.5.2; extra == "dev"
31
+ Requires-Dist: inflect==7.5.0; extra == "dev"
30
32
  Requires-Dist: ipykernel==6.29.5; extra == "dev"
31
33
  Requires-Dist: jaraco.collections==5.1.0; extra == "dev"
32
- Requires-Dist: nbstripout==0.7.1; extra == "dev"
34
+ Requires-Dist: nbstripout==0.8.1; extra == "dev"
33
35
  Requires-Dist: ordered-set==4.1.0; extra == "dev"
34
36
  Requires-Dist: pip-autoremove==0.10.0; extra == "dev"
35
37
  Requires-Dist: pip-chill==1.0.3; extra == "dev"
36
38
  Requires-Dist: pip-upgrade-outdated==1.5; extra == "dev"
37
39
  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"
40
+ Requires-Dist: pkginfo==1.12.1.2; extra == "dev"
41
+ Requires-Dist: pre-commit==4.2.0; extra == "dev"
42
+ Requires-Dist: pre-commit-hooks==5.0.0; extra == "dev"
43
+ Requires-Dist: py-env==0.0.1; extra == "dev"
44
+ Requires-Dist: pyright==1.1.399; extra == "dev"
45
+ Requires-Dist: pytest-check==2.5.3; extra == "dev"
46
+ Requires-Dist: pytest-cov==6.1.1; extra == "dev"
47
+ Requires-Dist: tomli==2.2.1; extra == "dev"
48
+ Requires-Dist: twine==6.1.0; extra == "dev"
49
+ Dynamic: license-file
43
50
 
44
51
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
45
52
  [![Checked with pyright](https://microsoft.github.io/pyright/img/pyright_badge.svg)](https://microsoft.github.io/pyright/)
@@ -49,7 +56,7 @@ Requires-Dist: twine==5.1.1; extra == "dev"
49
56
  This library offers tools to take advantage of
50
57
  the [internal API](https://app.swaggerhub.com/apis/OlivierMartineau/RudiProducer-InternalAPI) of a RUDI Producer node (
51
58
  also
52
- referred as RUDI node), through the API of the backend of the user interface, the "Producer node manager" or "Prodmanager" module.
59
+ referred as RUDI node), through the API of the backend of the user interface, the "Producer node manager" or "RUDI Manager" module.
53
60
 
54
61
  ## Installation
55
62
 
@@ -6,7 +6,7 @@
6
6
  This library offers tools to take advantage of
7
7
  the [internal API](https://app.swaggerhub.com/apis/OlivierMartineau/RudiProducer-InternalAPI) of a RUDI Producer node (
8
8
  also
9
- referred as RUDI node), through the API of the backend of the user interface, the "Producer node manager" or "Prodmanager" module.
9
+ referred as RUDI node), through the API of the backend of the user interface, the "Producer node manager" or "RUDI Manager" module.
10
10
 
11
11
  ## Installation
12
12
 
@@ -4,20 +4,31 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "rudi-node-write"
7
- version = "1.2.2"
7
+ version = "1.3.0"
8
8
  authors = [{ name = "Olivier Martineau", email = "olivier.martineau@irisa.fr" }]
9
- maintainers = [{ name = "Olivier Martineau", email = "olivier.martineau@irisa.fr" }]
9
+ maintainers = [
10
+ { name = "Olivier Martineau", email = "olivier.martineau@irisa.fr" },
11
+ ]
10
12
  description = "Use the internal API of a RUDI Producer node"
11
13
  readme = "README.md"
12
14
  requires-python = ">=3.11"
13
- license = { text = "EUPL-1.2" }
14
- classifiers = ["Programming Language :: Python :: 3.11",
15
+ license-files = ["LICENCE.md"]
16
+ license = "EUPL-1.2"
17
+ classifiers = [
18
+ "Programming Language :: Python :: 3.11",
15
19
  "Programming Language :: Python :: 3.12",
16
20
  "Natural Language :: English",
17
21
  "Operating System :: OS Independent",
18
- "License :: OSI Approved :: European Union Public Licence 1.2 (EUPL 1.2)",
19
22
  ]
20
- keywords = ["rudi-node-write", "rudi-node-put", "RUDI", "producer node", "RUDI node", "open-data", "Univ. Rennes"]
23
+ keywords = [
24
+ "rudi-node-write",
25
+ "rudi-node-put",
26
+ "RUDI",
27
+ "producer node",
28
+ "RUDI node",
29
+ "open-data",
30
+ "Univ. Rennes",
31
+ ]
21
32
  dynamic = ["dependencies", "optional-dependencies"]
22
33
  # dependencies = ["beautifulsoup4", "chardet", "deepdiff", "puremagic"]
23
34
 
@@ -34,7 +45,7 @@ target-version = ['py311']
34
45
  # ----- Tool: commitizen
35
46
  [tool.commitizen]
36
47
  name = "cz_conventional_commits"
37
- version = "1.2.2"
48
+ version = "1.3.0"
38
49
  version_files = ["pyproject.toml:version"]
39
50
 
40
51
  # ----- Tool: pytest
@@ -42,7 +53,12 @@ version_files = ["pyproject.toml:version"]
42
53
  pythonpath = ["src"]
43
54
  norecursedirs = ["*.egg", ".eggs", "dist", "build", "wip"]
44
55
  filterwarnings = ["ignore:.*pkg_resources.*:DeprecationWarning"]
45
- addopts = ["--cov=rudi_node_write", "--cov-report=term-missing", "--cov-report=html:reports/html_dir", "--cov-report=xml:reports/coverage.xml" ]
56
+ addopts = [
57
+ "--cov=rudi_node_write",
58
+ "--cov-report=term-missing",
59
+ "--cov-report=html:reports/html_dir",
60
+ "--cov-report=xml:reports/coverage.xml",
61
+ ]
46
62
 
47
63
  # ----- Tool: setuptools
48
64
  [tool.setuptools.packages.find]
@@ -50,17 +66,17 @@ where = ["src"]
50
66
  include = ["rudi_node_write*"]
51
67
 
52
68
  [tool.setuptools.dynamic]
53
- dependencies = {file = ["requirements.txt"]}
54
- optional-dependencies = {dev = { file = ["requirements-dev.txt"] }}
69
+ dependencies = { file = ["requirements.txt"] }
70
+ optional-dependencies = { dev = { file = ["requirements-dev.txt"] } }
55
71
 
56
72
  # ----- Tool: pyright
57
73
  [tool.pyright]
58
74
  exclude = ["**/node_modules", "**/__pycache__"]
59
75
  include = ["src"]
60
76
  pythonVersion = "3.11"
61
- reportMissingImports = "true"
62
- reportDuplicateImport = "true"
63
- reportUnusedImport = "true"
64
- reportImportCycles = "true"
77
+ reportMissingImports = true
78
+ reportDuplicateImport = true
79
+ reportUnusedImport = true
80
+ reportImportCycles = true
65
81
  venvPath = "."
66
82
  venv = ".venv"
@@ -0,0 +1,112 @@
1
+ backports.tarfile==1.2.0
2
+ black==25.1.0
3
+ build==1.2.2.post1
4
+ commitizen==4.6.0
5
+ flake8==7.2.0
6
+ importlib-metadata==8.6.1
7
+ importlib-resources==6.5.2
8
+ inflect==7.5.0
9
+ ipykernel==6.29.5
10
+ jaraco.collections==5.1.0
11
+ nbstripout==0.8.1
12
+ ordered-set==4.1.0
13
+ pip-autoremove==0.10.0
14
+ pip-chill==1.0.3
15
+ pip-upgrade-outdated==1.5
16
+ pip3-autoremove==1.2.2
17
+ pkginfo==1.12.1.2
18
+ pre-commit==4.2.0
19
+ pre-commit-hooks==5.0.0
20
+ py-env==0.0.1
21
+ pyright==1.1.399
22
+ pytest-check==2.5.3
23
+ pytest-cov==6.1.1
24
+ tomli==2.2.1
25
+ twine==6.1.0
26
+ # appnope==0.1.4 # Installed as dependency for ipykernel
27
+ # argcomplete==3.6.2 # Installed as dependency for commitizen
28
+ # asttokens==3.0.0 # Installed as dependency for stack-data
29
+ # attrs==25.3.0 # Installed as dependency for jsonschema, referencing
30
+ # autocommand==2.2.2 # Installed as dependency for jaraco.text
31
+ # certifi==2025.1.31 # Installed as dependency for requests
32
+ # cfgv==3.4.0 # Installed as dependency for pre-commit
33
+ # charset-normalizer==3.4.1 # Installed as dependency for commitizen, requests
34
+ # click==8.1.8 # Installed as dependency for black
35
+ # colorama==0.4.6 # Installed as dependency for commitizen
36
+ # comm==0.2.2 # Installed as dependency for ipykernel
37
+ # coverage==7.8.0 # Installed as dependency for pytest-cov
38
+ # debugpy==1.8.14 # Installed as dependency for ipykernel
39
+ # decli==0.6.2 # Installed as dependency for commitizen
40
+ # decorator==5.2.1 # Installed as dependency for ipython
41
+ # distlib==0.3.9 # Installed as dependency for virtualenv
42
+ # docutils==0.21.2 # Installed as dependency for readme-renderer
43
+ # executing==2.2.0 # Installed as dependency for stack-data
44
+ # fastjsonschema==2.21.1 # Installed as dependency for nbformat
45
+ # filelock==3.18.0 # Installed as dependency for virtualenv
46
+ # id==1.5.0 # Installed as dependency for twine
47
+ # identify==2.6.10 # Installed as dependency for pre-commit
48
+ # idna==3.10 # Installed as dependency for requests
49
+ # iniconfig==2.1.0 # Installed as dependency for pytest
50
+ # ipython==9.1.0 # Installed as dependency for ipykernel
51
+ # ipython-pygments-lexers==1.1.1 # Installed as dependency for ipython
52
+ # jaraco.classes==3.4.0 # Installed as dependency for keyring
53
+ # jaraco.context==6.0.1 # Installed as dependency for jaraco.text, keyring
54
+ # jaraco.functools==4.1.0 # Installed as dependency for jaraco.text, keyring
55
+ # jaraco.text==4.0.0 # Installed as dependency for jaraco.collections
56
+ # jedi==0.19.2 # Installed as dependency for ipython
57
+ # jinja2==3.1.6 # Installed as dependency for commitizen
58
+ # jsonschema==4.23.0 # Installed as dependency for nbformat
59
+ # jsonschema-specifications==2024.10.1 # Installed as dependency for jsonschema
60
+ # jupyter-client==8.6.3 # Installed as dependency for ipykernel
61
+ # jupyter-core==5.7.2 # Installed as dependency for ipykernel, jupyter-client, nbformat
62
+ # keyring==25.6.0 # Installed as dependency for twine
63
+ # markdown-it-py==3.0.0 # Installed as dependency for rich
64
+ # markupsafe==3.0.2 # Installed as dependency for jinja2
65
+ # matplotlib-inline==0.1.7 # Installed as dependency for ipykernel, ipython
66
+ # mccabe==0.7.0 # Installed as dependency for flake8
67
+ # mdurl==0.1.2 # Installed as dependency for markdown-it-py
68
+ # more-itertools==10.7.0 # Installed as dependency for inflect, jaraco.classes, jaraco.functools, jaraco.text
69
+ # mypy-extensions==1.1.0 # Installed as dependency for black
70
+ # nbformat==5.10.4 # Installed as dependency for nbstripout
71
+ # nest-asyncio==1.6.0 # Installed as dependency for ipykernel
72
+ # nh3==0.2.21 # Installed as dependency for readme-renderer
73
+ # nodeenv==1.9.1 # Installed as dependency for pre-commit, pyright
74
+ # packaging==25.0 # Installed as dependency for black, build, commitizen, ipykernel, pytest, twine
75
+ # parso==0.8.4 # Installed as dependency for jedi
76
+ # pathspec==0.12.1 # Installed as dependency for black
77
+ # pexpect==4.9.0 # Installed as dependency for ipython
78
+ # platformdirs==4.3.7 # Installed as dependency for black, jupyter-core, virtualenv
79
+ # pluggy==1.5.0 # Installed as dependency for pytest
80
+ # prompt-toolkit==3.0.51 # Installed as dependency for ipython, questionary
81
+ # psutil==7.0.0 # Installed as dependency for ipykernel
82
+ # ptyprocess==0.7.0 # Installed as dependency for pexpect
83
+ # pure-eval==0.2.3 # Installed as dependency for stack-data
84
+ # pycodestyle==2.13.0 # Installed as dependency for flake8
85
+ # pyflakes==3.3.2 # Installed as dependency for flake8
86
+ # pygments==2.19.1 # Installed as dependency for ipython, ipython-pygments-lexers, readme-renderer, rich
87
+ # pyproject-hooks==1.2.0 # Installed as dependency for build
88
+ # pytest==8.3.5 # Installed as dependency for pytest-check, pytest-cov
89
+ # python-dateutil==2.9.0.post0 # Installed as dependency for jupyter-client
90
+ # pyyaml==6.0.2 # Installed as dependency for commitizen, pre-commit
91
+ # pyzmq==26.4.0 # Installed as dependency for ipykernel, jupyter-client
92
+ # questionary==2.1.0 # Installed as dependency for commitizen
93
+ # readme-renderer==44.0 # Installed as dependency for twine
94
+ # referencing==0.36.2 # Installed as dependency for jsonschema, jsonschema-specifications
95
+ # requests==2.32.3 # Installed as dependency for id, requests-toolbelt, twine
96
+ # requests-toolbelt==1.0.0 # Installed as dependency for twine
97
+ # rfc3986==2.0.0 # Installed as dependency for twine
98
+ # rich==14.0.0 # Installed as dependency for twine
99
+ # rpds-py==0.24.0 # Installed as dependency for jsonschema, referencing
100
+ # ruamel.yaml==0.18.10 # Installed as dependency for pre-commit-hooks
101
+ # ruamel.yaml.clib==0.2.12 # Installed as dependency for ruamel.yaml
102
+ # six==1.17.0 # Installed as dependency for python-dateutil
103
+ # stack-data==0.6.3 # Installed as dependency for ipython
104
+ # termcolor==3.0.1 # Installed as dependency for commitizen
105
+ # tomlkit==0.13.2 # Installed as dependency for commitizen
106
+ # tornado==6.4.2 # Installed as dependency for ipykernel, jupyter-client
107
+ # traitlets==5.14.3 # Installed as dependency for comm, ipykernel, ipython, jupyter-client, jupyter-core, matplotlib-inline, nbformat
108
+ # typeguard==4.4.2 # Installed as dependency for inflect
109
+ # urllib3==2.4.0 # Installed as dependency for requests, twine
110
+ # virtualenv==20.30.0 # Installed as dependency for pre-commit
111
+ # wcwidth==0.2.13 # Installed as dependency for prompt-toolkit
112
+ # zipp==3.21.0 # Installed as dependency for importlib-metadata
@@ -0,0 +1,7 @@
1
+ beautifulsoup4==4.13.4
2
+ chardet==5.2.0
3
+ deepdiff==8.4.2
4
+ puremagic==1.28
5
+ # orderly-set==5.4.0 # Installed as dependency for deepdiff
6
+ # soupsieve==2.7 # Installed as dependency for beautifulsoup4
7
+ # typing-extensions==4.13.2 # Installed as dependency for beautifulsoup4, pyright, referencing, typeguard
@@ -7,7 +7,7 @@ from rudi_node_write.rudi_types.rudi_const import check_is_literal
7
7
  from rudi_node_write.rudi_types.serializable import Serializable
8
8
  from rudi_node_write.utils.dict_utils import is_dict, safe_get_key
9
9
  from rudi_node_write.utils.err import HttpError
10
- from rudi_node_write.utils.log import log_d_if, log_e, log_d
10
+ from rudi_node_write.utils.log import log_d_if, log_e, log_d, log_w
11
11
  from rudi_node_write.utils.str_utils import slash_join
12
12
  from rudi_node_write.utils.url_utils import get_response_cookies, url_encode_req_params
13
13
 
@@ -55,6 +55,9 @@ class Connector:
55
55
  self._set_url(server_url)
56
56
  self._cookies = None
57
57
 
58
+ self.should_log_request: bool = True
59
+ self.should_log_response: bool = False
60
+
58
61
  def _set_url(self, server_url: str):
59
62
  here = f"super.{self.class_name}._set_url"
60
63
  (scheme, netloc, path, query, fragment) = urlsplit(server_url)
@@ -73,6 +76,10 @@ class Connector:
73
76
  def full_url(self, relative_url: str = "/"):
74
77
  return slash_join(self.base_url, url_encode_req_params(relative_url))
75
78
 
79
+ def set_path(self, new_path: str):
80
+ self.path = new_path
81
+ self.base_url = slash_join(f"{self.scheme}://{self.host}", self.path)
82
+
76
83
  def full_path(self, relative_url: str = "/"):
77
84
  return slash_join("/", self.path, url_encode_req_params(relative_url))
78
85
 
@@ -92,7 +99,6 @@ class Connector:
92
99
  relative_url: str,
93
100
  headers: dict | None = None,
94
101
  keep_alive: bool = False,
95
- should_log_response: bool = False,
96
102
  ):
97
103
  """
98
104
  Download a file on the connector server
@@ -118,7 +124,7 @@ class Connector:
118
124
  log_e(here, f"ERR {response.status}", path_url)
119
125
  return None
120
126
  else:
121
- log_d_if(should_log_response, here, f"OK {response.status}", path_url)
127
+ log_d_if(self.should_log_response, here, f"OK {response.status}", path_url)
122
128
  res_data = response.read()
123
129
  if not keep_alive and not self.keep_connection:
124
130
  self.connection.close()
@@ -133,9 +139,7 @@ class Connector:
133
139
  body: dict | str | list | Serializable | BinaryIO | TextIO | None = None,
134
140
  headers=None,
135
141
  keep_alive: bool = False,
136
- should_log_request: bool = False,
137
- should_log_response: bool = False,
138
- ):
142
+ ) -> dict | str | list | None:
139
143
  """
140
144
  Send a http(s) request
141
145
  :param relative_url: a relative URL that will be joined to the connector's base URL to form the request URL
@@ -153,23 +157,28 @@ class Connector:
153
157
 
154
158
  if headers is None:
155
159
  headers = DEFAULT_HEADERS
156
- if isinstance(body, dict):
157
- headers["Content-Type"] = "application/json"
158
- body_str = dumps(body)
159
- elif isinstance(body, Serializable):
160
- headers["Content-Type"] = "application/json"
161
- body_str = body.to_json_str(ensure_ascii=True)
162
- elif isinstance(body, list):
163
- body_str = str(list)
160
+ if req_method == "POST" or req_method == "PUT":
161
+ if isinstance(body, dict):
162
+ headers["Content-Type"] = "application/json"
163
+ body_str = dumps(body)
164
+ elif isinstance(body, Serializable):
165
+ headers["Content-Type"] = "application/json"
166
+ body_str = body.to_json_str(ensure_ascii=True)
167
+ elif isinstance(body, list):
168
+ body_str = str(list)
169
+ else:
170
+ body_str = body
164
171
  else:
165
- body_str = body
172
+ # log_w(here, f"Body is ignored since http method used is {req_method}")
173
+ body_str = None
166
174
 
167
175
  path_url = self.full_path(relative_url)
168
176
  if self.host is None:
169
177
  raise ConnectionError("The connector host should be defined")
170
178
  self.connection = HTTPConnection(self.host) if self.scheme == "http" else HTTPSConnection(self.host)
171
179
 
172
- log_d_if(should_log_request, here, req_method, self.full_url(relative_url))
180
+ # log_d_if(self.should_log_request, here, req_method, self.full_url(relative_url))
181
+ log_d_if(self.should_log_request, here, req_method, self.full_url(relative_url))
173
182
 
174
183
  try:
175
184
  self.connection.request(method=req_method, url=path_url, body=body_str, headers=headers) # type: ignore
@@ -177,19 +186,35 @@ class Connector:
177
186
  log_e(here, "Error on request", req_method, self.full_url(relative_url))
178
187
  log_e(here, "ERR", e)
179
188
  raise e
180
- return self.parse_response(
189
+ res = self.parse_response(
181
190
  relative_url=relative_url,
182
191
  req_method=req_method,
183
192
  keep_alive=keep_alive,
184
- should_log_response=should_log_response,
185
193
  )
194
+ return res
195
+ # if not isinstance(res, dict):
196
+ # return res
197
+ # redirect_url = res.get("redirection")
198
+ # if redirect_url is None:
199
+ # return res
200
+
201
+ # try:
202
+ # self.request(method=req_method, url=redirect_url, body=body_str, headers=headers) # type: ignore
203
+ # except ConnectionRefusedError as e:
204
+ # log_e(here, "Error on redirected request", req_method, self.full_url(relative_url))
205
+ # log_e(here, "ERR", e)
206
+ # raise e
207
+ # return self.parse_response(
208
+ # relative_url=relative_url,
209
+ # req_method=req_method,
210
+ # keep_alive=keep_alive,
211
+ # )
186
212
 
187
213
  def parse_response(
188
214
  self,
189
215
  relative_url: str,
190
216
  req_method: HttpRequestMethod,
191
217
  keep_alive: bool = False,
192
- should_log_response: bool = True,
193
218
  ):
194
219
  """Basic parsing of the result"""
195
220
  here = f"{self.class_name}.parse_response"
@@ -198,37 +223,38 @@ class Connector:
198
223
  response = self.connection.getresponse()
199
224
  self._cookies = get_response_cookies(response)
200
225
 
201
- if response.status in [301, 302]:
202
- return {STATUS: response.status, REDIRECTION: response.getheader("location")}
203
- if (
204
- response.status not in [200, 500, 501]
205
- and not (530 <= response.status < 540)
206
- and not (400 <= response.status < 500)
207
- ):
208
- return None
226
+ if response.status in [301, 302, 307, 308]:
227
+ return {"status": response.status, "from": relative_url, "redirection": response.getheader("location")}
228
+
229
+ # if (
230
+ # response.status not in [200, 500, 501]
231
+ # and not (530 <= response.status < 540)
232
+ # and not (400 <= response.status < 500)
233
+ # ):
234
+ # return None
209
235
 
210
236
  rdata = response.read()
211
237
  # log_d(here, "rdata", rdata)
212
238
  try:
213
239
  response_data = loads(rdata)
214
- log_d_if(should_log_response, here, "Response is a JSON", response_data)
240
+ log_d_if(self.should_log_response, here, "Response is a JSON", response_data)
215
241
  except (TypeError, JSONDecodeError):
216
242
  response_data = repr(rdata)
217
- log_d_if(should_log_response, here, "Response is not a JSON", response_data)
243
+ log_d_if(self.should_log_response, here, "Response is not a JSON", response_data)
218
244
  if not keep_alive and not self.keep_connection:
219
245
  self.close_connection()
220
246
 
221
247
  if type(response_data) is str:
222
- log_d_if(should_log_response, here, "Response is a string", response_data)
223
- if response.status == 200:
248
+ log_d_if(self.should_log_response, here, "Response is a string", response_data)
249
+ if response.status < 400:
224
250
  return rdata.decode("utf8")
225
- if response.status == 200:
251
+ if response.status < 400:
226
252
  return response_data
227
- if response.status >= 400:
228
- log_e(here, "Connection error", response_data)
229
- log_e(here, "Request in error", req_method, self.full_url(relative_url))
230
- # log_e(here, "Headers", response.headers)
231
- raise HttpError(response_data, req_method, self.base_url, relative_url)
253
+
254
+ log_e(here, "Connection error", response_data)
255
+ log_e(here, "Request in error", req_method, self.full_url(relative_url))
256
+ # log_e(here, "Headers", response.headers)
257
+ raise HttpError(response_data, response.status, req_method, self.base_url, relative_url)
232
258
 
233
259
 
234
260
  if __name__ == "__main__": # pragma: no cover
@@ -41,20 +41,20 @@ _STATUS_SKIPPED = "skipped"
41
41
  _STATUS_MISSING = "missing"
42
42
  _STATUS_DOWNLOADED = "downloaded"
43
43
 
44
- here = "RudiNodeApiConnector"
44
+ here = "RudiNodeCatalogConnector"
45
45
 
46
46
 
47
47
  def ensure_url_startswith_api_admin(url):
48
48
  return ensure_url_startswith(url, "api/admin")
49
49
 
50
50
 
51
- class RudiNodeApiConnector(Connector):
51
+ class RudiNodeCatalogConnector(Connector):
52
52
  def __init__(
53
53
  self,
54
54
  server_url: str,
55
55
  jwt_factory: RudiNodeJwtFactory | None = None,
56
56
  jwt: str | None = None,
57
- headers_user_agent: str = "RudiNodeApiConnector",
57
+ headers_user_agent: str = "RudiNodeCatalogConnector",
58
58
  ):
59
59
  """
60
60
  Creates a connector to the internal API of the API/proxy module of a RUDI producer node.
@@ -116,9 +116,7 @@ class RudiNodeApiConnector(Connector):
116
116
  def _headers(self):
117
117
  return self._initial_headers | {"Authorization": f"Bearer {self._jwt}"}
118
118
 
119
- def get_admin_api(
120
- self, url: str, keep_alive: bool = False, should_log_request=False, should_log_response=False
121
- ) -> str | int | list | dict:
119
+ def get_admin_api(self, url: str, keep_alive: bool = False) -> str | int | list | dict:
122
120
  """
123
121
  Performs an identified GET request through /api/admin path
124
122
  :param url: part of the URL that comes after /api/admin
@@ -131,8 +129,6 @@ class RudiNodeApiConnector(Connector):
131
129
  relative_url=ensure_url_startswith_api_admin(url),
132
130
  headers=self._headers,
133
131
  keep_alive=keep_alive,
134
- should_log_request=should_log_request,
135
- should_log_response=should_log_response,
136
132
  ) # type: ignore
137
133
 
138
134
  def put_admin_api(
@@ -637,7 +633,7 @@ class RudiNodeApiConnector(Connector):
637
633
  :param local_download_dir: the path to a local folder
638
634
  :return: an object that states if the file was downloaded, skipped or found missing
639
635
  """
640
- here = "RudiNodeApiConnector.download_file_from_media_info"
636
+ here = "RudiNodeCatalogConnector.download_file_from_media_info"
641
637
 
642
638
  media_type = media.get("media_type")
643
639
 
@@ -771,26 +767,26 @@ class RudiNodeApiConnector(Connector):
771
767
 
772
768
  if __name__ == "__main__": # pragma: no cover
773
769
  # ----------- INIT -----------
774
- tests = "RudiNodeApiConnector tests"
770
+ tests = "RudiNodeCatalogConnector tests"
775
771
  begin = time()
776
772
  creds_file = "../creds/creds_bas.json"
777
773
  rudi_node_creds = read_json_file(creds_file)
778
774
  url = rudi_node_creds["url"]
779
775
 
780
- node_jwt_factory = RudiNodeJwtFactory(url, rudi_node_creds)
781
- rudi_node_api = RudiNodeApiConnector(server_url=url, jwt_factory=node_jwt_factory)
776
+ jwt_factory = RudiNodeJwtFactory(url, rudi_node_creds)
777
+ catalog = RudiNodeCatalogConnector(server_url=url, jwt_factory=jwt_factory)
782
778
 
783
779
  # ----------- TESTS -----------
784
780
  test_dir = "../dwnld"
785
- log_d(tests, "producers", len(rudi_node_api.organization_list))
786
- log_d(tests, "producer names", rudi_node_api.producer_names)
787
- log_d(tests, "metadata_contacts", len(rudi_node_api.contact_list))
788
- log_d(tests, "contact names", rudi_node_api.contact_names)
781
+ log_d(tests, "producers", len(catalog.organization_list))
782
+ log_d(tests, "producer names", catalog.producer_names)
783
+ log_d(tests, "metadata_contacts", len(catalog.contact_list))
784
+ log_d(tests, "contact names", catalog.contact_names)
789
785
 
790
- log_d(tests, "themes", len(rudi_node_api.themes))
791
- log_d(tests, "used_themes", len(rudi_node_api.used_themes))
792
- log_d(tests, "keywords", len(rudi_node_api.keywords))
793
- log_d(tests, "used_keywords", len(rudi_node_api.used_keywords))
786
+ log_d(tests, "themes", len(catalog.themes))
787
+ log_d(tests, "used_themes", len(catalog.used_themes))
788
+ log_d(tests, "keywords", len(catalog.keywords))
789
+ log_d(tests, "used_keywords", len(catalog.used_keywords))
794
790
 
795
791
  #
796
792
  # log_d(here, ' get_metadata_with_media_uuid',
@@ -800,25 +796,25 @@ if __name__ == "__main__": # pragma: no cover
800
796
  log_d(
801
797
  tests,
802
798
  "download_files_for_metadata",
803
- rudi_node_api.download_files_for_metadata("65d99589-7a7a-46a3-afe8-c5a47b964310", test_dir),
799
+ catalog.download_files_for_metadata("65d99589-7a7a-46a3-afe8-c5a47b964310", test_dir),
804
800
  )
805
801
 
806
802
  log_d(
807
803
  tests,
808
804
  "download_file_with_media_uuid '782bab2d-7ee8-4633-9c0a-173649b4d879'",
809
- rudi_node_api.download_file_with_media_uuid("fef11852-0756-4cbe-bdfb-3722a1751de9", test_dir),
805
+ catalog.download_file_with_media_uuid("fef11852-0756-4cbe-bdfb-3722a1751de9", test_dir),
810
806
  )
811
807
 
812
808
  log_d(
813
809
  tests,
814
810
  "download_file_with_name '782bab2d-7ee8-4633-9c0a-173649b4d879'",
815
- rudi_node_api.download_file_with_name("782bab2d-7ee8-4633-9c0a-173649b4d879", test_dir),
811
+ catalog.download_file_with_name("782bab2d-7ee8-4633-9c0a-173649b4d879", test_dir),
816
812
  )
817
813
 
818
814
  log_d(
819
815
  tests,
820
816
  "download_file_with_name 'toucan.jpg'",
821
- "\n" + str(rudi_node_api.download_file_with_name("toucan.jpg", test_dir)),
817
+ "\n" + str(catalog.download_file_with_name("toucan.jpg", test_dir)),
822
818
  )
823
819
 
824
820
  log_d(tests, "exec. time", time() - begin)
@@ -46,7 +46,7 @@ class RudiNodeJwtFactory(Connector):
46
46
 
47
47
  def test_connection(self):
48
48
  test = self.request(relative_url="crypto/jwt", req_method="GET", headers=self._headers)
49
- if not isinstance(test, dict) or test["RUDI"] != "JWT":
49
+ if not isinstance(test, dict) or test.get("RUDI") != "JWT":
50
50
  log_e("RudiNodeJwtFactory", f"!! Node '{self.host}'", "no connection!")
51
51
  raise ConnectionError(f"An error occurred while connecting to RUDI node JWT server {self.base_url}")
52
52
  # log_d("RudiNodeJwtFactory", f"Node '{self.host}'", "connection OK")