rudi-node-write 1.4.2__tar.gz → 1.4.4__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.4.2/src/rudi_node_write.egg-info → rudi_node_write-1.4.4}/PKG-INFO +1 -1
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/pyproject.toml +2 -2
- rudi_node_write-1.4.2/src/rudi_node_write/connectors/io_rudi_manager_write_v3.py → rudi_node_write-1.4.4/src/rudi_node_write/connectors/io_rudi_manager_write.py +67 -32
- rudi_node_write-1.4.4/src/rudi_node_write/connectors/io_rudi_manager_write_v2.py +12 -0
- rudi_node_write-1.4.4/src/rudi_node_write/connectors/io_rudi_manager_write_v3.py +12 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/connectors/rudi_node_auth.py +4 -1
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/rudi_types/rudi_const.py +10 -130
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/utils/file_utils.py +1 -80
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/utils/jwt.py +7 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4/src/rudi_node_write.egg-info}/PKG-INFO +1 -1
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/tests/test_rudi_node_write.py +1 -1
- rudi_node_write-1.4.2/src/rudi_node_write/connectors/io_rudi_manager_write.py +0 -1444
- rudi_node_write-1.4.2/src/rudi_node_write/connectors/io_rudi_manager_write_v2.py +0 -124
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/LICENCE.md +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/README.md +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/requirements-dev.txt +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/requirements.txt +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/setup.cfg +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/__init__.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/conf/meta_defaults.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/connectors/io_connector.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/connectors/io_rudi_catalog_write.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/connectors/io_rudi_jwt_factory.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/connectors/io_rudi_storage_write.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/rudi_node_writer.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/rudi_types/rudi_contact.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/rudi_types/rudi_dates.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/rudi_types/rudi_dictionary_entry.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/rudi_types/rudi_geo.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/rudi_types/rudi_licence.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/rudi_types/rudi_media.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/rudi_types/rudi_meta.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/rudi_types/rudi_meta_misc.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/rudi_types/rudi_org.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/rudi_types/serializable.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/utils/dict_utils.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/utils/err.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/utils/html_utils.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/utils/list_utils.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/utils/log.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/utils/str_utils.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/utils/type_date.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/utils/typing_utils.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/utils/url_utils.py +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write.egg-info/SOURCES.txt +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write.egg-info/dependency_links.txt +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write.egg-info/requires.txt +0 -0
- {rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "rudi-node-write"
|
|
3
|
-
version = "1.4.
|
|
3
|
+
version = "1.4.4"
|
|
4
4
|
authors = [{ name = "Olivier Martineau", email = "olivier.martineau@irisa.fr" }]
|
|
5
5
|
maintainers = [
|
|
6
6
|
{ name = "Olivier Martineau", email = "olivier.martineau@irisa.fr" },
|
|
@@ -45,7 +45,7 @@ target-version = ['py311']
|
|
|
45
45
|
# ----- Tool: commitizen
|
|
46
46
|
[tool.commitizen]
|
|
47
47
|
name = "cz_conventional_commits"
|
|
48
|
-
version = "1.4.
|
|
48
|
+
version = "1.4.4"
|
|
49
49
|
version_files = ["pyproject.toml:version"]
|
|
50
50
|
|
|
51
51
|
# ----- Tool: pytest
|
|
@@ -6,10 +6,6 @@ from typing import Literal
|
|
|
6
6
|
from urllib.parse import quote
|
|
7
7
|
|
|
8
8
|
from rudi_node_write.connectors.io_connector import Connector, https_download
|
|
9
|
-
from rudi_node_write.connectors.io_rudi_manager_write import (
|
|
10
|
-
CONSOLE_JWT_NAME,
|
|
11
|
-
RudiNodeManagerConnector,
|
|
12
|
-
)
|
|
13
9
|
from rudi_node_write.connectors.rudi_node_auth import RudiNodeAuth
|
|
14
10
|
from rudi_node_write.rudi_types.rudi_const import (
|
|
15
11
|
MEDIA_TYPE_FILE,
|
|
@@ -49,22 +45,28 @@ from rudi_node_write.utils.typing_utils import check_is_int, get_type_name
|
|
|
49
45
|
from rudi_node_write.utils.url_utils import ensure_url_startswith
|
|
50
46
|
|
|
51
47
|
# Defaults for constructor
|
|
52
|
-
_DEFAULT_USER_AGENT = "
|
|
48
|
+
_DEFAULT_USER_AGENT = "RudiNodeManagerConnector"
|
|
49
|
+
|
|
50
|
+
# Cookie names
|
|
51
|
+
MANAGER_JWT_NAME = "pmFrontToken"
|
|
52
|
+
CONSOLE_JWT_NAME = "consoleToken"
|
|
53
53
|
|
|
54
54
|
# Manager API prefixes
|
|
55
55
|
MGR_CATALOG_PREFIX = "catalog"
|
|
56
56
|
OLD_MGR_CATALOG_PREFIX = "data"
|
|
57
57
|
|
|
58
|
+
# Data retrieving, cache
|
|
58
59
|
REQ_LIMIT = 500
|
|
59
60
|
_DELAY_REFRESH_S = 60 # seconds
|
|
60
61
|
_REFRESH_KEY = "refresh_time" # seconds
|
|
61
62
|
|
|
63
|
+
# Download status
|
|
62
64
|
_STATUS_SKIPPED = "skipped"
|
|
63
65
|
_STATUS_MISSING = "missing"
|
|
64
66
|
_STATUS_DOWNLOADED = "downloaded"
|
|
65
67
|
|
|
66
68
|
|
|
67
|
-
here = "
|
|
69
|
+
here = "RudiNodeManagerConnector"
|
|
68
70
|
|
|
69
71
|
|
|
70
72
|
def ensure_url_startswith_catalog(url):
|
|
@@ -73,13 +75,10 @@ def ensure_url_startswith_catalog(url):
|
|
|
73
75
|
return ensure_url_startswith(url, MGR_CATALOG_PREFIX)
|
|
74
76
|
|
|
75
77
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
class RudiNodeManagerConnectorV3(RudiNodeManagerConnector):
|
|
78
|
+
class RudiNodeManagerConnector(Connector):
|
|
80
79
|
"""
|
|
81
|
-
Every RUDI node has a UI module called "RUDI node manager", or "Manager" for shorts
|
|
82
|
-
|
|
80
|
+
Every RUDI node has a UI module called "RUDI node manager", or "Manager" for shorts.
|
|
81
|
+
It offers to list, edit or create RUDI metadata, given that you have the required level of access.
|
|
83
82
|
This library takes advantage of the manager backend API to send data and metadata.
|
|
84
83
|
"GenC" stands for "Generation C", as this particular file takes advantage of the 3rd generation of RUDI node interface.
|
|
85
84
|
"""
|
|
@@ -92,28 +91,51 @@ class RudiNodeManagerConnectorV3(RudiNodeManagerConnector):
|
|
|
92
91
|
headers_user_agent: str = _DEFAULT_USER_AGENT,
|
|
93
92
|
keep_connection: bool = False,
|
|
94
93
|
):
|
|
95
|
-
super().__init__(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
)
|
|
94
|
+
super().__init__(server_url=server_url, keep_connection=keep_connection)
|
|
95
|
+
|
|
96
|
+
self.server_url = server_url
|
|
97
|
+
|
|
98
|
+
if isinstance(auth, RudiNodeAuth):
|
|
99
|
+
self._auth = auth
|
|
100
|
+
elif isinstance(auth, dict):
|
|
101
|
+
self._auth = RudiNodeAuth(b64url_auth=auth["b64url_auth"], usr=auth["usr"], pwd=auth["pwd"])
|
|
102
|
+
else:
|
|
103
|
+
raise TypeError("Input 'auth' parameter should either be a 'RudiNodeAuth' object or a dict.")
|
|
104
|
+
|
|
105
|
+
self.name = name
|
|
106
|
+
if self.name is None:
|
|
107
|
+
self.name = self.server_url.split(".")[0].split("/")[-1]
|
|
108
|
+
|
|
109
|
+
self._headers_user_agent = headers_user_agent
|
|
110
|
+
|
|
102
111
|
self._gen = 3
|
|
103
112
|
|
|
104
|
-
self._cached_api_version = None
|
|
105
|
-
self._cached_conf = None
|
|
113
|
+
self._cached_api_version: str | None = None
|
|
114
|
+
self._cached_conf: dict | None = None
|
|
115
|
+
|
|
116
|
+
self._cached_manager_jwt: str | None = None
|
|
117
|
+
self._cached_manager_headers: dict | None = None
|
|
106
118
|
|
|
107
|
-
self.
|
|
108
|
-
self.
|
|
119
|
+
self._cached_storage_url: str | None = None
|
|
120
|
+
self._cached_storage_jwt: str | None = None
|
|
121
|
+
self._cached_storage_connector: RudiNodeStorageConnector | None = None
|
|
109
122
|
|
|
110
|
-
self.
|
|
111
|
-
self.
|
|
112
|
-
|
|
123
|
+
self.manager_url: str | None = None
|
|
124
|
+
self.manager_path: str | None = None
|
|
125
|
+
|
|
126
|
+
self._data_cache = {}
|
|
113
127
|
|
|
114
128
|
self.conf
|
|
115
129
|
# self.test_identified_connection()
|
|
116
130
|
|
|
131
|
+
@property
|
|
132
|
+
def _usr(self):
|
|
133
|
+
return self._auth.usr
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def _pwd(self):
|
|
137
|
+
return self._auth.pwd
|
|
138
|
+
|
|
117
139
|
@property
|
|
118
140
|
def conf(self):
|
|
119
141
|
if self._cached_conf is None:
|
|
@@ -138,6 +160,16 @@ class RudiNodeManagerConnectorV3(RudiNodeManagerConnector):
|
|
|
138
160
|
raise NotImplementedError("This node version is not compatible with this object") from e
|
|
139
161
|
return self._cached_conf
|
|
140
162
|
|
|
163
|
+
@property
|
|
164
|
+
def storage_url(self) -> str:
|
|
165
|
+
return self._cached_storage_url or self.conf["storagePubUrl"]
|
|
166
|
+
|
|
167
|
+
@property
|
|
168
|
+
def portal_url(self) -> str | None:
|
|
169
|
+
if self.node_urls is not None:
|
|
170
|
+
return self.node_urls.get("portal_url")
|
|
171
|
+
return None
|
|
172
|
+
|
|
141
173
|
# ----------[ Basic API calls ]-------------------------------------------------------------------------------------
|
|
142
174
|
def get_api(self, url: str, headers: dict, keep_alive: bool = False):
|
|
143
175
|
"""
|
|
@@ -303,7 +335,7 @@ class RudiNodeManagerConnectorV3(RudiNodeManagerConnector):
|
|
|
303
335
|
@property
|
|
304
336
|
def storage_connector(self):
|
|
305
337
|
if self._cached_storage_connector is None:
|
|
306
|
-
self._cached_storage_connector =
|
|
338
|
+
self._cached_storage_connector = RudiNodeStorageConnector(self.storage_url, self._storage_jwt)
|
|
307
339
|
if is_jwt_expired(self._cached_storage_connector.jwt):
|
|
308
340
|
self._cached_storage_connector.jwt = self._storage_jwt
|
|
309
341
|
return self._cached_storage_connector
|
|
@@ -417,7 +449,7 @@ class RudiNodeManagerConnectorV3(RudiNodeManagerConnector):
|
|
|
417
449
|
:param obj_type: one of RUDI object types
|
|
418
450
|
:return: the list of objects for this type
|
|
419
451
|
"""
|
|
420
|
-
here = f"{self.class_name}.
|
|
452
|
+
here = f"{self.class_name}.get_catalog_cached"
|
|
421
453
|
|
|
422
454
|
if obj_type in RUDI_OBJECT_TYPES:
|
|
423
455
|
if not (self._gen == 1 and obj_type == "media"):
|
|
@@ -428,6 +460,9 @@ class RudiNodeManagerConnectorV3(RudiNodeManagerConnector):
|
|
|
428
460
|
else:
|
|
429
461
|
return self.get_cache(ensure_url_startswith_catalog(obj_type))
|
|
430
462
|
|
|
463
|
+
def get_data(self, obj_type: RudiObjectTypeStr | str) -> list[dict] | dict: # type: ignore
|
|
464
|
+
return self.get_catalog_cached(obj_type)
|
|
465
|
+
|
|
431
466
|
# ----------[ Requesting data ]-------------------------------------------------------------------------------------
|
|
432
467
|
|
|
433
468
|
def _count_obj(self, obj_type: RudiObjectTypeStr | str) -> int:
|
|
@@ -1225,7 +1260,7 @@ class RudiNodeManagerConnectorV3(RudiNodeManagerConnector):
|
|
|
1225
1260
|
return ack
|
|
1226
1261
|
|
|
1227
1262
|
|
|
1228
|
-
class
|
|
1263
|
+
class RudiNodeStorageConnector(Connector):
|
|
1229
1264
|
def __init__(self, server_url: str, jwt: str):
|
|
1230
1265
|
super().__init__(server_url)
|
|
1231
1266
|
self.jwt = jwt
|
|
@@ -1407,14 +1442,14 @@ class FileTooBigException(Exception):
|
|
|
1407
1442
|
|
|
1408
1443
|
if __name__ == "__main__": # pragma: no cover
|
|
1409
1444
|
begin = time()
|
|
1410
|
-
tests = "
|
|
1445
|
+
tests = "RudiNodeManagerConnector tests"
|
|
1411
1446
|
creds_file = "../creds/creds_pytest.json"
|
|
1412
1447
|
rudi_node_creds = read_json_file(creds_file)
|
|
1413
1448
|
manager_url = slash_join(rudi_node_creds["url"], "manager")
|
|
1414
1449
|
log_d(tests, "node_url", manager_url)
|
|
1415
1450
|
auth = RudiNodeAuth.from_json(rudi_node_creds)
|
|
1416
1451
|
|
|
1417
|
-
manager =
|
|
1452
|
+
manager = RudiNodeManagerConnector(server_url=manager_url, auth=auth)
|
|
1418
1453
|
log_d(tests, "catalog_url", manager.catalog_url)
|
|
1419
1454
|
log_d(tests, "storage_url", manager.storage_url)
|
|
1420
1455
|
log_d(tests, "manager_url", manager.manager_url)
|
|
@@ -1443,7 +1478,7 @@ if __name__ == "__main__": # pragma: no cover
|
|
|
1443
1478
|
log_d(tests, "rudi_media_url", storage_url)
|
|
1444
1479
|
|
|
1445
1480
|
# "Hack" when no SSL connection is available
|
|
1446
|
-
storage =
|
|
1481
|
+
storage = RudiNodeStorageConnector(server_url=storage_url, jwt=manager._storage_jwt)
|
|
1447
1482
|
storage.scheme = "http"
|
|
1448
1483
|
storage.should_log_response = True
|
|
1449
1484
|
manager._cached_storage_connector = storage
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from rudi_node_write.connectors.io_rudi_manager_write import (
|
|
2
|
+
RudiNodeManagerConnector,
|
|
3
|
+
RudiNodeStorageConnector,
|
|
4
|
+
)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class RudiNodeManagerConnectorV2(RudiNodeManagerConnector):
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class RudiNodeStorageConnectorV2(RudiNodeStorageConnector):
|
|
12
|
+
pass
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from rudi_node_write.connectors.io_rudi_manager_write import (
|
|
2
|
+
RudiNodeManagerConnector,
|
|
3
|
+
RudiNodeStorageConnector,
|
|
4
|
+
)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class RudiNodeManagerConnectorV3(RudiNodeManagerConnector):
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class RudiNodeStorageConnectorV3(RudiNodeStorageConnector):
|
|
12
|
+
pass
|
{rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/connectors/rudi_node_auth.py
RENAMED
|
@@ -2,6 +2,7 @@ from base64 import urlsafe_b64decode, urlsafe_b64encode
|
|
|
2
2
|
|
|
3
3
|
from rudi_node_write.rudi_types.serializable import Serializable
|
|
4
4
|
from rudi_node_write.utils.jwt import is_base64_url, pad_b64_str
|
|
5
|
+
from rudi_node_write.utils.log import log_d
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
class RudiNodeAuth(Serializable):
|
|
@@ -16,12 +17,14 @@ class RudiNodeAuth(Serializable):
|
|
|
16
17
|
- either a `b64url_auth` URL-safe Base64 encoded `usr:pwd` string
|
|
17
18
|
- or with a couple of `usr` and `pwd` strings
|
|
18
19
|
"""
|
|
20
|
+
here = "RudiNodeAuth"
|
|
19
21
|
if b64url_auth is not None:
|
|
20
22
|
self._b64_auth = pad_b64_str(b64url_auth)
|
|
23
|
+
log_d(here, "self._b64_auth", self._b64_auth)
|
|
21
24
|
if not is_base64_url(self._b64_auth):
|
|
22
25
|
raise ValueError("The input `b64url_auth` should be a urlsafe-base64 string.")
|
|
23
26
|
try:
|
|
24
|
-
self.usr, self.pwd = urlsafe_b64decode(
|
|
27
|
+
self.usr, self.pwd = urlsafe_b64decode(self._b64_auth).decode("utf-8").split(":")
|
|
25
28
|
except Exception as e:
|
|
26
29
|
raise ValueError(
|
|
27
30
|
"The input `b64url_auth` should be a urlsafe-base64 string that encodes a `usr:pwd` string couple"
|
{rudi_node_write-1.4.2 → rudi_node_write-1.4.4}/src/rudi_node_write/rudi_types/rudi_const.py
RENAMED
|
@@ -109,6 +109,7 @@ FileExtensions: Final = {
|
|
|
109
109
|
".bmp": "image/bmp",
|
|
110
110
|
".bz": "application/x-bzip",
|
|
111
111
|
".bz2": "application/x-bzip2",
|
|
112
|
+
".cdf": "application/netcdf",
|
|
112
113
|
".css": "text/css",
|
|
113
114
|
".csv": "text/csv",
|
|
114
115
|
".doc": "application/msword",
|
|
@@ -118,6 +119,7 @@ FileExtensions: Final = {
|
|
|
118
119
|
".flif": "image/flif",
|
|
119
120
|
".geojson": "application/geo+json",
|
|
120
121
|
".gif": "image/gif",
|
|
122
|
+
".gpkg": "application/geopackage+sqlite3",
|
|
121
123
|
".gz": "application/gzip",
|
|
122
124
|
".gzip": "application/gzip",
|
|
123
125
|
".htm": "text/html",
|
|
@@ -129,6 +131,7 @@ FileExtensions: Final = {
|
|
|
129
131
|
".json": "application/json",
|
|
130
132
|
".jsonld": "application/ld+json",
|
|
131
133
|
".m4a": "audio/m4a",
|
|
134
|
+
".md": "text/markdown",
|
|
132
135
|
".mkv": "video/x-matroska",
|
|
133
136
|
".mng": "image/x-mng",
|
|
134
137
|
".mov": "video/quicktime",
|
|
@@ -136,6 +139,7 @@ FileExtensions: Final = {
|
|
|
136
139
|
".mp4": "video/mp4",
|
|
137
140
|
".mpeg": "video/mpeg",
|
|
138
141
|
".mpg": "video/mpeg",
|
|
142
|
+
".nc": "application/netcdf",
|
|
139
143
|
".odp": "application/vnd.oasis.opendocument.presentation",
|
|
140
144
|
".ods": "application/vnd.oasis.opendocument.spreadsheet",
|
|
141
145
|
".odt": "application/vnd.oasis.opendocument.text",
|
|
@@ -148,7 +152,6 @@ FileExtensions: Final = {
|
|
|
148
152
|
".png": "image/png",
|
|
149
153
|
".ppt": "application/vnd.ms-powerpoint",
|
|
150
154
|
".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
151
|
-
".py": "text/x-python",
|
|
152
155
|
".sql": "application/sql",
|
|
153
156
|
".tar": "application/x-tar",
|
|
154
157
|
".tar.bz": "application/x-bzip",
|
|
@@ -157,6 +160,7 @@ FileExtensions: Final = {
|
|
|
157
160
|
".tgz": "application/gzip",
|
|
158
161
|
".tif": "image/tiff",
|
|
159
162
|
".tiff": "image/tiff",
|
|
163
|
+
".toml": "application/toml",
|
|
160
164
|
".ttf": "font/ttf",
|
|
161
165
|
".txt": "text/plain",
|
|
162
166
|
".wav": "audio/wav",
|
|
@@ -174,141 +178,17 @@ FileExtensions: Final = {
|
|
|
174
178
|
}
|
|
175
179
|
FILE_EXTENSIONS = get_args(FileExtensions)
|
|
176
180
|
|
|
177
|
-
|
|
178
|
-
"application/epub+zip",
|
|
179
|
-
"application/geo+json",
|
|
181
|
+
_MIME_TYPES_EXTRA: Final[tuple[str, ...]] = (
|
|
180
182
|
"application/graphql",
|
|
181
|
-
"application/gzip",
|
|
182
|
-
"application/javascript",
|
|
183
|
-
"application/json",
|
|
184
|
-
"application/ld+json",
|
|
185
|
-
"application/msword",
|
|
186
|
-
"application/octet-stream",
|
|
187
|
-
"application/pdf",
|
|
188
|
-
"application/sql",
|
|
189
183
|
"application/vnd.api+json",
|
|
190
|
-
"application/vnd.ms-excel",
|
|
191
|
-
"application/vnd.ms-powerpoint",
|
|
192
|
-
"application/vnd.oasis.opendocument.presentation",
|
|
193
|
-
"application/vnd.oasis.opendocument.spreadsheet",
|
|
194
|
-
"application/vnd.oasis.opendocument.text",
|
|
195
|
-
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
196
|
-
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
197
|
-
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
198
|
-
"application/x-7z-compressed",
|
|
199
|
-
"application/x-bzip",
|
|
200
|
-
"application/x-bzip2",
|
|
201
|
-
"application/x-executable",
|
|
202
|
-
"application/x-tar",
|
|
203
184
|
"application/x-www-form-urlencoded",
|
|
204
185
|
"application/xml",
|
|
205
|
-
"application/zip",
|
|
206
|
-
"application/zstd",
|
|
207
|
-
"audio/aac",
|
|
208
|
-
"audio/m4a",
|
|
209
|
-
"audio/mpeg",
|
|
210
|
-
"audio/ogg",
|
|
211
|
-
"audio/wav",
|
|
212
|
-
"audio/webm",
|
|
213
|
-
"font/otf",
|
|
214
|
-
"font/ttf",
|
|
215
|
-
"image/apng",
|
|
216
|
-
"image/bmp",
|
|
217
|
-
"image/flif",
|
|
218
|
-
"image/gif",
|
|
219
|
-
"image/jpeg",
|
|
220
|
-
"image/png",
|
|
221
|
-
"image/tiff",
|
|
222
|
-
"image/vnd.microsoft.icon",
|
|
223
|
-
"image/webp",
|
|
224
|
-
"image/x-mng",
|
|
225
186
|
"multipart/form-data",
|
|
226
|
-
"text/css",
|
|
227
|
-
"text/csv",
|
|
228
|
-
"text/html",
|
|
229
|
-
"text/markdown",
|
|
230
|
-
"text/php",
|
|
231
|
-
"text/plain",
|
|
232
187
|
"text/x-markdown",
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
"video/mpeg",
|
|
238
|
-
"video/ogg",
|
|
239
|
-
"video/quicktime",
|
|
240
|
-
"video/webm",
|
|
241
|
-
"video/x-matroska",
|
|
242
|
-
"video/x-ms-wmv",
|
|
243
|
-
"video/x-msvideo",
|
|
244
|
-
"application/epub+zip+crypt",
|
|
245
|
-
"application/geo+json+crypt",
|
|
246
|
-
"application/graphql+crypt",
|
|
247
|
-
"application/gzip+crypt",
|
|
248
|
-
"application/javascript+crypt",
|
|
249
|
-
"application/json+crypt",
|
|
250
|
-
"application/ld+json+crypt",
|
|
251
|
-
"application/msword+crypt",
|
|
252
|
-
"application/octet-stream+crypt",
|
|
253
|
-
"application/pdf+crypt",
|
|
254
|
-
"application/sql+crypt",
|
|
255
|
-
"application/vnd.api+json+crypt",
|
|
256
|
-
"application/vnd.ms-excel+crypt",
|
|
257
|
-
"application/vnd.ms-powerpoint+crypt",
|
|
258
|
-
"application/vnd.oasis.opendocument.presentation+crypt",
|
|
259
|
-
"application/vnd.oasis.opendocument.spreadsheet+crypt",
|
|
260
|
-
"application/vnd.oasis.opendocument.text+crypt",
|
|
261
|
-
"application/vnd.openxmlformats-officedocument.presentationml.presentation+crypt",
|
|
262
|
-
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet+crypt",
|
|
263
|
-
"application/vnd.openxmlformats-officedocument.wordprocessingml.document+crypt",
|
|
264
|
-
"application/x-7z-compressed+crypt",
|
|
265
|
-
"application/x-bzip+crypt",
|
|
266
|
-
"application/x-bzip2+crypt",
|
|
267
|
-
"application/x-executable+crypt",
|
|
268
|
-
"application/x-tar+crypt",
|
|
269
|
-
"application/x-www-form-urlencoded+crypt",
|
|
270
|
-
"application/xml+crypt",
|
|
271
|
-
"application/zip+crypt",
|
|
272
|
-
"application/zstd+crypt",
|
|
273
|
-
"audio/aac+crypt",
|
|
274
|
-
"audio/m4a+crypt",
|
|
275
|
-
"audio/mpeg+crypt",
|
|
276
|
-
"audio/ogg+crypt",
|
|
277
|
-
"audio/wav+crypt",
|
|
278
|
-
"audio/webm+crypt",
|
|
279
|
-
"font/otf+crypt",
|
|
280
|
-
"font/ttf+crypt",
|
|
281
|
-
"image/apng+crypt",
|
|
282
|
-
"image/bmp+crypt",
|
|
283
|
-
"image/flif+crypt",
|
|
284
|
-
"image/gif+crypt",
|
|
285
|
-
"image/jpeg+crypt",
|
|
286
|
-
"image/png+crypt",
|
|
287
|
-
"image/tiff+crypt",
|
|
288
|
-
"image/vnd.microsoft.icon+crypt",
|
|
289
|
-
"image/webp+crypt",
|
|
290
|
-
"image/x-mng+crypt",
|
|
291
|
-
"multipart/form-data+crypt",
|
|
292
|
-
"text/css+crypt",
|
|
293
|
-
"text/csv+crypt",
|
|
294
|
-
"text/html+crypt",
|
|
295
|
-
"text/markdown+crypt",
|
|
296
|
-
"text/php+crypt",
|
|
297
|
-
"text/plain+crypt",
|
|
298
|
-
"text/x-markdown+crypt",
|
|
299
|
-
"text/x-yaml+crypt",
|
|
300
|
-
"text/xml+crypt",
|
|
301
|
-
"video/3gpp+crypt",
|
|
302
|
-
"video/mp4+crypt",
|
|
303
|
-
"video/mpeg+crypt",
|
|
304
|
-
"video/ogg+crypt",
|
|
305
|
-
"video/quicktime+crypt",
|
|
306
|
-
"video/webm+crypt",
|
|
307
|
-
"video/x-matroska+crypt",
|
|
308
|
-
"video/x-ms-wmv+crypt",
|
|
309
|
-
"video/x-msvideo+crypt",
|
|
310
|
-
]
|
|
311
|
-
MIME_TYPES = get_args(MimeTypes)
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
_MIME_TYPES_BASE: Final[tuple[str, ...]] = tuple(sorted(set(FileExtensions.values()) | set(_MIME_TYPES_EXTRA)))
|
|
191
|
+
MIME_TYPES: Final[tuple[str, ...]] = _MIME_TYPES_BASE + tuple(f"{m}+crypt" for m in _MIME_TYPES_BASE)
|
|
312
192
|
|
|
313
193
|
MimeTypesUtf8Text = Literal[
|
|
314
194
|
"application/geo+json",
|
|
@@ -13,85 +13,6 @@ from rudi_node_write.rudi_types.rudi_const import FileExtensions
|
|
|
13
13
|
from rudi_node_write.rudi_types.serializable import Serializable
|
|
14
14
|
from rudi_node_write.utils.log import log_d, log_w
|
|
15
15
|
|
|
16
|
-
EXTENSIONS = {
|
|
17
|
-
".3gp": "video/3gpp",
|
|
18
|
-
".3gpp": "video/3gpp",
|
|
19
|
-
".7z": "application/x-7z-compressed",
|
|
20
|
-
".aac": "audio/aac",
|
|
21
|
-
".apng": "image/apng",
|
|
22
|
-
".avi": "video/x-msvideo",
|
|
23
|
-
".bin": "application/octet-stream",
|
|
24
|
-
".bmp": "image/bmp",
|
|
25
|
-
".bz": "application/x-bzip",
|
|
26
|
-
".bz2": "application/x-bzip2",
|
|
27
|
-
".cdf": "application/netcdf",
|
|
28
|
-
".css": "text/css",
|
|
29
|
-
".csv": "text/csv",
|
|
30
|
-
".doc": "application/msword",
|
|
31
|
-
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
32
|
-
".epub": "application/epub+zip",
|
|
33
|
-
".exe": "application/x-executable",
|
|
34
|
-
".flif": "image/flif",
|
|
35
|
-
".geojson": "application/geo+json",
|
|
36
|
-
".gif": "image/gif",
|
|
37
|
-
".gpkg": "application/geopackage+sqlite3",
|
|
38
|
-
".gz": "application/gzip",
|
|
39
|
-
".gzip": "application/gzip",
|
|
40
|
-
".htm": "text/html",
|
|
41
|
-
".html": "text/html",
|
|
42
|
-
".ico": "image/vnd.microsoft.icon",
|
|
43
|
-
".jpeg": "image/jpeg",
|
|
44
|
-
".jpg": "image/jpeg",
|
|
45
|
-
".js": "application/javascript",
|
|
46
|
-
".json": "application/json",
|
|
47
|
-
".jsonld": "application/ld+json",
|
|
48
|
-
".m4a": "audio/m4a",
|
|
49
|
-
".md": "text/markdown",
|
|
50
|
-
".mkv": "video/x-matroska",
|
|
51
|
-
".mng": "image/x-mng",
|
|
52
|
-
".mov": "video/quicktime",
|
|
53
|
-
".mp3": "audio/mpeg",
|
|
54
|
-
".mp4": "video/mp4",
|
|
55
|
-
".mpeg": "video/mpeg",
|
|
56
|
-
".mpg": "video/mpeg",
|
|
57
|
-
".nc": "application/netcdf",
|
|
58
|
-
".odp": "application/vnd.oasis.opendocument.presentation",
|
|
59
|
-
".ods": "application/vnd.oasis.opendocument.spreadsheet",
|
|
60
|
-
".odt": "application/vnd.oasis.opendocument.text",
|
|
61
|
-
".oga": "audio/ogg",
|
|
62
|
-
".ogg": "audio/ogg",
|
|
63
|
-
".ogv": "video/ogg",
|
|
64
|
-
".otf": "font/otf",
|
|
65
|
-
".pdf": "application/pdf",
|
|
66
|
-
".php": "text/php",
|
|
67
|
-
".png": "image/png",
|
|
68
|
-
".ppt": "application/vnd.ms-powerpoint",
|
|
69
|
-
".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
70
|
-
".sql": "application/sql",
|
|
71
|
-
".tar": "application/x-tar",
|
|
72
|
-
".tar.bz": "application/x-bzip",
|
|
73
|
-
".tar.bz2": "application/x-bzip2",
|
|
74
|
-
".tar.gz": "application/gzip",
|
|
75
|
-
".tgz": "application/gzip",
|
|
76
|
-
".tif": "image/tiff",
|
|
77
|
-
".tiff": "image/tiff",
|
|
78
|
-
".toml": "application/toml",
|
|
79
|
-
".ttf": "font/ttf",
|
|
80
|
-
".txt": "text/plain",
|
|
81
|
-
".wav": "audio/wav",
|
|
82
|
-
".weba": "audio/webm",
|
|
83
|
-
".webm": "video/webm",
|
|
84
|
-
".webp": "image/webp",
|
|
85
|
-
".wmv": "video/x-ms-wmv",
|
|
86
|
-
".xls": "application/vnd.ms-excel",
|
|
87
|
-
".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
88
|
-
".xml": "text/xml",
|
|
89
|
-
".yaml": "text/x-yaml",
|
|
90
|
-
".yml": "text/x-yaml",
|
|
91
|
-
".zip": "application/zip",
|
|
92
|
-
".zst": "application/zstd",
|
|
93
|
-
}
|
|
94
|
-
|
|
95
16
|
|
|
96
17
|
def is_dir(dir_local_path: str):
|
|
97
18
|
return Path(dir_local_path).is_dir()
|
|
@@ -157,7 +78,7 @@ def get_file_mime(file_local_path: str) -> str:
|
|
|
157
78
|
"""
|
|
158
79
|
here = "get_file_mime"
|
|
159
80
|
file_ext = get_file_extension(file_local_path)
|
|
160
|
-
if mime :=
|
|
81
|
+
if mime := FileExtensions.get(file_ext):
|
|
161
82
|
return mime
|
|
162
83
|
|
|
163
84
|
check_is_file(file_local_path)
|
|
@@ -67,3 +67,10 @@ def is_jwt_expired(jwt) -> bool:
|
|
|
67
67
|
except ValueError as e:
|
|
68
68
|
log_e("is_jwt_expired", f"this is not a JWT: '{jwt}'", e)
|
|
69
69
|
return True
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
if __name__ == "__main__": # pragma: no cover
|
|
73
|
+
for arg in ["testing", "YrmFjpOshYMxl0tth73NhYmtl4GFzew"]:
|
|
74
|
+
print("* is_base64_url", f"'{arg}'? ->", is_base64_url(arg))
|
|
75
|
+
arg = pad_b64_str(arg)
|
|
76
|
+
print("* is_base64_url", f"'{arg}'? ->", is_base64_url(arg))
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
from time import time
|
|
2
|
+
|
|
2
3
|
from rudi_node_write.connectors.rudi_node_auth import RudiNodeAuth
|
|
3
4
|
from rudi_node_write.rudi_node_writer import RudiNodeWriter
|
|
4
5
|
from rudi_node_write.rudi_types.rudi_org import RudiOrganization
|
|
5
6
|
from rudi_node_write.utils.file_utils import read_json_file
|
|
6
|
-
from rudi_node_write.utils.log import log_d
|
|
7
7
|
from rudi_node_write.utils.str_utils import is_uuid_v4, slash_join
|
|
8
8
|
|
|
9
9
|
begin = time()
|