bluer-objects 6.104.1__py3-none-any.whl → 6.464.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. bluer_objects/.abcli/abcli.sh +6 -0
  2. bluer_objects/.abcli/alias.sh +13 -6
  3. bluer_objects/.abcli/assets/cd.sh +20 -0
  4. bluer_objects/.abcli/assets/mv.sh +34 -0
  5. bluer_objects/.abcli/assets/publish.sh +40 -0
  6. bluer_objects/.abcli/assets.sh +15 -0
  7. bluer_objects/.abcli/create_test_asset.sh +10 -0
  8. bluer_objects/.abcli/download.sh +3 -1
  9. bluer_objects/.abcli/file.sh +15 -4
  10. bluer_objects/.abcli/gif.sh +18 -0
  11. bluer_objects/.abcli/host.sh +23 -7
  12. bluer_objects/.abcli/ls.sh +19 -8
  13. bluer_objects/.abcli/metadata/download.sh +9 -0
  14. bluer_objects/.abcli/metadata/edit.sh +15 -0
  15. bluer_objects/.abcli/metadata/upload.sh +9 -0
  16. bluer_objects/.abcli/mlflow/browse.sh +2 -0
  17. bluer_objects/.abcli/mlflow/deploy.sh +21 -5
  18. bluer_objects/.abcli/mlflow/lock/lock.sh +11 -0
  19. bluer_objects/.abcli/mlflow/lock/unlock.sh +12 -0
  20. bluer_objects/.abcli/mlflow/lock.sh +15 -0
  21. bluer_objects/.abcli/mlflow/tags/search.sh +1 -5
  22. bluer_objects/.abcli/mlflow.sh +0 -2
  23. bluer_objects/.abcli/pdf/convert.sh +92 -0
  24. bluer_objects/.abcli/pdf.sh +15 -0
  25. bluer_objects/.abcli/storage/clear.sh +2 -0
  26. bluer_objects/.abcli/tests/clone.sh +2 -3
  27. bluer_objects/.abcli/tests/create_test_asset.sh +16 -0
  28. bluer_objects/.abcli/tests/file.sh +64 -0
  29. bluer_objects/.abcli/tests/gif.sh +3 -3
  30. bluer_objects/.abcli/tests/help.sh +23 -7
  31. bluer_objects/.abcli/tests/ls.sh +11 -4
  32. bluer_objects/.abcli/tests/metadata.sh +35 -0
  33. bluer_objects/.abcli/tests/mlflow_lock.sh +30 -0
  34. bluer_objects/.abcli/tests/mlflow_tags.sh +1 -1
  35. bluer_objects/.abcli/tests/open.sh +11 -0
  36. bluer_objects/.abcli/tests/open_gif_open.sh +14 -0
  37. bluer_objects/.abcli/tests/pdf.sh +39 -0
  38. bluer_objects/.abcli/tests/storage_clear.sh +11 -0
  39. bluer_objects/.abcli/tests/storage_public_upload.sh +25 -0
  40. bluer_objects/.abcli/tests/storage_status.sh +12 -0
  41. bluer_objects/.abcli/tests/{storage.sh → storage_upload_download.sh} +26 -8
  42. bluer_objects/.abcli/upload.sh +26 -2
  43. bluer_objects/README/__init__.py +7 -22
  44. bluer_objects/README/alias.py +67 -0
  45. bluer_objects/README/build/__init__.py +0 -0
  46. bluer_objects/README/build/aliases.py +23 -0
  47. bluer_objects/README/build/docs.py +23 -0
  48. bluer_objects/README/build/modules.py +9 -0
  49. bluer_objects/README/consts.py +44 -0
  50. bluer_objects/README/functions.py +154 -204
  51. bluer_objects/README/items.py +78 -6
  52. bluer_objects/README/process/__init__.py +0 -0
  53. bluer_objects/README/process/assets.py +36 -0
  54. bluer_objects/README/process/details.py +20 -0
  55. bluer_objects/README/process/envs.py +23 -0
  56. bluer_objects/README/process/help.py +27 -0
  57. bluer_objects/README/process/include.py +40 -0
  58. bluer_objects/README/process/legacy.py +21 -0
  59. bluer_objects/README/process/mermaid.py +20 -0
  60. bluer_objects/README/process/national_internet.py +55 -0
  61. bluer_objects/README/process/objects.py +32 -0
  62. bluer_objects/README/process/signature.py +35 -0
  63. bluer_objects/README/process/title.py +44 -0
  64. bluer_objects/README/process/variables.py +12 -0
  65. bluer_objects/__init__.py +1 -1
  66. bluer_objects/assets/__init__.py +0 -0
  67. bluer_objects/assets/__main__.py +57 -0
  68. bluer_objects/assets/functions.py +62 -0
  69. bluer_objects/config.env +13 -1
  70. bluer_objects/env.py +27 -1
  71. bluer_objects/file/__main__.py +52 -7
  72. bluer_objects/file/functions.py +21 -4
  73. bluer_objects/file/load.py +2 -9
  74. bluer_objects/file/save.py +17 -24
  75. bluer_objects/graphics/__main__.py +7 -0
  76. bluer_objects/graphics/gif.py +11 -7
  77. bluer_objects/graphics/screen.py +9 -8
  78. bluer_objects/help/assets.py +93 -0
  79. bluer_objects/help/create_test_asset.py +22 -0
  80. bluer_objects/help/download.py +17 -3
  81. bluer_objects/help/file.py +59 -0
  82. bluer_objects/help/functions.py +9 -1
  83. bluer_objects/help/gif.py +25 -0
  84. bluer_objects/help/host.py +6 -4
  85. bluer_objects/help/ls.py +26 -3
  86. bluer_objects/help/metadata.py +51 -0
  87. bluer_objects/help/mlflow/__init__.py +23 -2
  88. bluer_objects/help/mlflow/cache.py +2 -4
  89. bluer_objects/help/mlflow/lock.py +52 -0
  90. bluer_objects/help/mlflow/tags.py +34 -23
  91. bluer_objects/help/pdf.py +67 -0
  92. bluer_objects/help/upload.py +10 -3
  93. bluer_objects/host/functions.py +4 -1
  94. bluer_objects/logger/confusion_matrix.py +76 -0
  95. bluer_objects/logger/image.py +110 -0
  96. bluer_objects/logger/stitch.py +107 -0
  97. bluer_objects/markdown.py +8 -6
  98. bluer_objects/metadata/__init__.py +1 -0
  99. bluer_objects/metadata/flatten.py +27 -0
  100. bluer_objects/mlflow/__init__.py +1 -1
  101. bluer_objects/mlflow/__main__.py +49 -31
  102. bluer_objects/mlflow/lock/__init__.py +1 -0
  103. bluer_objects/mlflow/lock/__main__.py +58 -0
  104. bluer_objects/mlflow/lock/functions.py +121 -0
  105. bluer_objects/mlflow/logging.py +53 -41
  106. bluer_objects/mlflow/models.py +7 -0
  107. bluer_objects/mlflow/objects.py +7 -0
  108. bluer_objects/mlflow/runs.py +10 -1
  109. bluer_objects/mlflow/serverless/__init__.py +3 -0
  110. bluer_objects/mlflow/serverless/api.py +88 -0
  111. bluer_objects/mlflow/serverless/read.py +19 -0
  112. bluer_objects/mlflow/serverless/search.py +35 -0
  113. bluer_objects/mlflow/serverless/write.py +42 -0
  114. bluer_objects/mlflow/tags.py +59 -9
  115. bluer_objects/objects.py +3 -1
  116. bluer_objects/pdf/__init__.py +1 -0
  117. bluer_objects/pdf/__main__.py +78 -0
  118. bluer_objects/pdf/convert/__init__.py +0 -0
  119. bluer_objects/pdf/convert/batch.py +54 -0
  120. bluer_objects/pdf/convert/combination.py +32 -0
  121. bluer_objects/pdf/convert/convert.py +110 -0
  122. bluer_objects/pdf/convert/image.py +53 -0
  123. bluer_objects/pdf/convert/md.py +97 -0
  124. bluer_objects/pdf/convert/missing.py +96 -0
  125. bluer_objects/pdf/convert/pdf.py +37 -0
  126. bluer_objects/sample.env +6 -0
  127. bluer_objects/storage/WebDAV.py +11 -7
  128. bluer_objects/storage/WebDAVrequest.py +360 -0
  129. bluer_objects/storage/WebDAVzip.py +26 -29
  130. bluer_objects/storage/__init__.py +28 -1
  131. bluer_objects/storage/__main__.py +40 -6
  132. bluer_objects/storage/base.py +84 -5
  133. bluer_objects/storage/policies.py +7 -0
  134. bluer_objects/storage/s3.py +367 -0
  135. bluer_objects/testing/__main__.py +6 -0
  136. bluer_objects/tests/test_README_consts.py +71 -0
  137. bluer_objects/tests/test_README_items.py +128 -0
  138. bluer_objects/tests/test_alias.py +33 -0
  139. bluer_objects/tests/test_env.py +42 -7
  140. bluer_objects/tests/test_file_download.py +30 -0
  141. bluer_objects/tests/test_file_load_save.py +1 -2
  142. bluer_objects/tests/test_file_load_save_text.py +46 -0
  143. bluer_objects/tests/test_graphics_gif.py +2 -0
  144. bluer_objects/tests/test_log_image_grid.py +29 -0
  145. bluer_objects/tests/test_logger_confusion_matrix.py +18 -0
  146. bluer_objects/tests/test_logger_matrix.py +2 -2
  147. bluer_objects/tests/test_logger_stitch_images.py +47 -0
  148. bluer_objects/tests/test_metadata.py +12 -6
  149. bluer_objects/tests/test_metadata_flatten.py +109 -0
  150. bluer_objects/tests/test_mlflow.py +114 -5
  151. bluer_objects/tests/test_mlflow_lock.py +26 -0
  152. bluer_objects/tests/test_objects.py +2 -0
  153. bluer_objects/tests/test_shell.py +34 -0
  154. bluer_objects/tests/test_storage.py +8 -21
  155. bluer_objects/tests/test_storage_base.py +39 -0
  156. bluer_objects/tests/test_storage_s3.py +67 -0
  157. bluer_objects/tests/test_storage_webdav_request.py +75 -0
  158. bluer_objects/tests/test_storage_webdav_zip.py +42 -0
  159. bluer_objects/tests/test_web_is_accessible.py +11 -0
  160. {bluer_objects-6.104.1.dist-info → bluer_objects-6.464.1.dist-info}/METADATA +20 -11
  161. bluer_objects-6.464.1.dist-info/RECORD +228 -0
  162. {bluer_objects-6.104.1.dist-info → bluer_objects-6.464.1.dist-info}/WHEEL +1 -1
  163. bluer_objects/.abcli/storage/download_file.sh +0 -9
  164. bluer_objects/.abcli/storage/exists.sh +0 -8
  165. bluer_objects/.abcli/storage/list.sh +0 -8
  166. bluer_objects/.abcli/storage/rm.sh +0 -11
  167. bluer_objects/.abcli/tests/mlflow_test.sh +0 -7
  168. bluer_objects-6.104.1.dist-info/RECORD +0 -143
  169. {bluer_objects-6.104.1.dist-info → bluer_objects-6.464.1.dist-info}/licenses/LICENSE +0 -0
  170. {bluer_objects-6.104.1.dist-info → bluer_objects-6.464.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,37 @@
1
+ from bluer_objects import file, objects
2
+ from bluer_objects.env import abcli_path_git
3
+ from bluer_objects.logger import logger
4
+
5
+
6
+ def convert_pdf(
7
+ source_filename: str,
8
+ suffix: str,
9
+ object_name: str,
10
+ list_of_pdfs: list[str],
11
+ ) -> bool:
12
+ logger.info("🌠 pdf found!")
13
+ filename_pdf = file.add_extension(
14
+ objects.path_of(
15
+ filename="docs/{}".format(
16
+ (
17
+ suffix.split(abcli_path_git, 1)[1]
18
+ if abcli_path_git in suffix
19
+ else suffix
20
+ ),
21
+ ),
22
+ object_name=object_name,
23
+ ),
24
+ "pdf",
25
+ )
26
+
27
+ if filename_pdf not in list_of_pdfs:
28
+ list_of_pdfs.append(filename_pdf)
29
+
30
+ if file.exists(filename_pdf):
31
+ logger.info(f"✅ {filename_pdf}")
32
+ return True
33
+
34
+ return file.copy(
35
+ source_filename,
36
+ filename_pdf,
37
+ )
bluer_objects/sample.env CHANGED
@@ -1,3 +1,9 @@
1
+ S3_STORAGE_ENDPOINT_URL=
2
+ S3_STORAGE_AWS_ACCESS_KEY_ID=
3
+ S3_STORAGE_AWS_SECRET_ACCESS_KEY=
4
+
5
+ MLFLOW_DEPLOYMENT=local
6
+
1
7
  WEBDAV_HOSTNAME=
2
8
  WEBDAV_LOGIN=
3
9
  WEBDAV_PASSWORD=
@@ -4,6 +4,7 @@ from webdav3.client import Client
4
4
  from bluer_objects.storage.base import StorageInterface
5
5
  from bluer_objects import env, file, path
6
6
  from bluer_objects import objects
7
+ from bluer_objects.storage.policies import DownloadPolicy
7
8
  from bluer_objects.logger import logger
8
9
 
9
10
 
@@ -56,6 +57,7 @@ class WebDAVInterface(StorageInterface):
56
57
  object_name: str,
57
58
  filename: str = "",
58
59
  log: bool = True,
60
+ policy: DownloadPolicy = DownloadPolicy.NONE,
59
61
  ) -> bool:
60
62
  local_path = objects.path_of(
61
63
  object_name=object_name,
@@ -80,21 +82,21 @@ class WebDAVInterface(StorageInterface):
80
82
  object_name=object_name,
81
83
  filename=filename,
82
84
  log=log,
85
+ policy=policy,
83
86
  )
84
87
 
85
- def ls(
86
- self,
87
- object_name: str,
88
- where: str = "local",
89
- ) -> Tuple[bool, List[str]]:
90
- assert False, "not implemented"
91
-
92
88
  def upload(
93
89
  self,
94
90
  object_name: str,
95
91
  filename: str = "",
92
+ public: bool = False,
93
+ zip: bool = False,
96
94
  log: bool = True,
97
95
  ) -> bool:
96
+ if public or zip:
97
+ logger.error("public/zip upload not supported.")
98
+ return False
99
+
98
100
  if filename:
99
101
  remote_dir = "/".join([object_name] + filename.split("/")[:-1])
100
102
  if not self.mkdir(
@@ -118,5 +120,7 @@ class WebDAVInterface(StorageInterface):
118
120
  return super().upload(
119
121
  object_name=object_name,
120
122
  filename=filename,
123
+ public=public,
124
+ zip=zip,
121
125
  log=log,
122
126
  )
@@ -0,0 +1,360 @@
1
+ import requests
2
+ from requests.auth import HTTPBasicAuth
3
+ import glob
4
+ from typing import Tuple, List
5
+ from xml.etree import ElementTree as ET
6
+ from tqdm import tqdm
7
+
8
+ from bluer_objects.storage.base import StorageInterface
9
+ from bluer_objects import env, file, path
10
+ from bluer_objects import objects
11
+ from bluer_objects.storage.policies import DownloadPolicy
12
+ from bluer_objects.logger import logger
13
+
14
+
15
+ # https://chatgpt.com/c/6824cf43-6738-8005-8733-54b6a77f20ee
16
+ class WebDAVRequestInterface(StorageInterface):
17
+ name = "webdav-request"
18
+
19
+ def clear(
20
+ self,
21
+ do_dryrun: bool = True,
22
+ log: bool = True,
23
+ public: bool = False,
24
+ ) -> bool:
25
+ if not super().clear(
26
+ do_dryrun=do_dryrun,
27
+ log=log,
28
+ public=public,
29
+ ):
30
+ return False
31
+
32
+ success, list_of_objects = self.list_raw(
33
+ suffix="",
34
+ recursive=False,
35
+ )
36
+ if not success:
37
+ return False
38
+
39
+ count: int = 0
40
+ for thing in tqdm(list_of_objects):
41
+ thing_name = thing.split(f"{env.WEBDAV_LOGIN}/", 1)[1]
42
+ if not thing_name.startswith("test"):
43
+ continue
44
+
45
+ if not thing_name.endswith("/"):
46
+ continue
47
+
48
+ if not self.delete(
49
+ object_name=thing_name.split("/", 1)[0],
50
+ do_dryrun=do_dryrun,
51
+ log=log,
52
+ ):
53
+ return False
54
+
55
+ count += 1
56
+
57
+ logger.info(f"deleted {count} object(s).")
58
+ return True
59
+
60
+ def delete(
61
+ self,
62
+ object_name: str,
63
+ do_dryrun: bool = True,
64
+ log: bool = True,
65
+ ) -> bool:
66
+ if log:
67
+ logger.info(
68
+ "{}.delete({}){}".format(
69
+ self.__class__.__name__,
70
+ object_name,
71
+ " dryrun" if do_dryrun else "",
72
+ )
73
+ )
74
+ if do_dryrun:
75
+ return True
76
+
77
+ try:
78
+ response = requests.request(
79
+ method="DELETE",
80
+ url=f"{env.WEBDAV_HOSTNAME}/{object_name}/",
81
+ auth=HTTPBasicAuth(
82
+ env.WEBDAV_LOGIN,
83
+ env.WEBDAV_PASSWORD,
84
+ ),
85
+ )
86
+ except Exception as e:
87
+ logger.error(e)
88
+ return False
89
+
90
+ if response.status_code in [200, 204]:
91
+ return True
92
+
93
+ logger.error(f"failed to delete: {response.status_code} - {response.text}")
94
+ return False
95
+
96
+ def mkdir(
97
+ self,
98
+ path: str,
99
+ log: bool = True,
100
+ ) -> bool:
101
+ url = f"{env.WEBDAV_HOSTNAME}/"
102
+ for folder in path.split("/"):
103
+ url = f"{url}{folder}/"
104
+
105
+ try:
106
+ response = requests.request(
107
+ "MKCOL",
108
+ url,
109
+ auth=HTTPBasicAuth(
110
+ env.WEBDAV_LOGIN,
111
+ env.WEBDAV_PASSWORD,
112
+ ),
113
+ )
114
+ except Exception as e:
115
+ logger.error(e)
116
+ return False
117
+
118
+ if response.status_code == 405: # Already exists
119
+ continue
120
+
121
+ if response.status_code == 201: # Created
122
+ if log:
123
+ logger.info(
124
+ "{}.mkdir {}".format(
125
+ self.__class__.__name__,
126
+ url.split(env.WEBDAV_HOSTNAME, 1)[1],
127
+ )
128
+ )
129
+ continue
130
+
131
+ logger.error(f"failed to create: {response.status_code} - {response.text}")
132
+ return False
133
+
134
+ return True
135
+
136
+ def download(
137
+ self,
138
+ object_name: str,
139
+ filename: str = "",
140
+ log: bool = True,
141
+ policy: DownloadPolicy = DownloadPolicy.NONE,
142
+ ) -> bool:
143
+ if filename:
144
+ local_path = objects.path_of(
145
+ object_name=object_name,
146
+ filename=filename,
147
+ create=True,
148
+ )
149
+
150
+ if not path.create(file.path(local_path)):
151
+ return False
152
+
153
+ url = f"{env.WEBDAV_HOSTNAME}/{object_name}/{filename}"
154
+
155
+ try:
156
+ response = requests.get(
157
+ url,
158
+ auth=HTTPBasicAuth(
159
+ env.WEBDAV_LOGIN,
160
+ env.WEBDAV_PASSWORD,
161
+ ),
162
+ )
163
+ except Exception as e:
164
+ logger.error(e)
165
+ return False
166
+
167
+ if response.status_code == 404: # object not found
168
+ return True
169
+
170
+ if response.status_code == 200:
171
+ try:
172
+ with open(local_path, "wb") as file_:
173
+ file_.write(response.content)
174
+ except Exception as e:
175
+ logger.error(e)
176
+ return False
177
+
178
+ return super().download(
179
+ object_name=object_name,
180
+ filename=filename,
181
+ log=log,
182
+ policy=policy,
183
+ )
184
+
185
+ logger.error(f"failed to download: {response.status_code}")
186
+ return False
187
+
188
+ success, list_of_files = self.ls(
189
+ object_name=object_name,
190
+ where="cloud",
191
+ )
192
+ if not success:
193
+ return False
194
+
195
+ for filename_ in tqdm(list_of_files):
196
+ if not self.download(
197
+ object_name=object_name,
198
+ filename=filename_,
199
+ log=log,
200
+ policy=policy,
201
+ ):
202
+ return False
203
+
204
+ return True
205
+
206
+ def list_raw(
207
+ self,
208
+ suffix: str,
209
+ recursive: bool,
210
+ ) -> Tuple[bool, List[str]]:
211
+ # https://chatgpt.com/c/6824f8d3-d9c0-8005-a7fa-d646f812f4b7
212
+ headers = {
213
+ "Depth": "infinity" if recursive else "1",
214
+ "Content-Type": "application/xml",
215
+ }
216
+
217
+ # Minimal PROPFIND XML body
218
+ data = """<?xml version="1.0"?>
219
+ <d:propfind xmlns:d="DAV:">
220
+ <d:prop><d:displayname/></d:prop>
221
+ </d:propfind>"""
222
+
223
+ try:
224
+ response = requests.request(
225
+ method="PROPFIND",
226
+ url=f"{env.WEBDAV_HOSTNAME}/{suffix}",
227
+ data=data,
228
+ headers=headers,
229
+ auth=HTTPBasicAuth(
230
+ env.WEBDAV_LOGIN,
231
+ env.WEBDAV_PASSWORD,
232
+ ),
233
+ )
234
+ except Exception as e:
235
+ logger.error(e)
236
+ return False, []
237
+
238
+ if response.status_code == 404: # object not found
239
+ return True, []
240
+
241
+ if response.status_code in (207, 207):
242
+ tree = ET.fromstring(response.content)
243
+ ns = {"d": "DAV:"}
244
+ list_of_files = []
245
+ for resp in tree.findall("d:response", ns):
246
+ href = resp.find("d:href", ns).text
247
+ list_of_files.append(href)
248
+
249
+ return True, list_of_files
250
+
251
+ logger.error(f"failed to list: {response.status_code} - {response.text}")
252
+ return False, []
253
+
254
+ def ls(
255
+ self,
256
+ object_name: str,
257
+ where: str = "local",
258
+ ) -> Tuple[bool, List[str]]:
259
+ if where == "cloud":
260
+ success, list_of_files = self.list_raw(
261
+ suffix=f"{object_name}/",
262
+ recursive=True,
263
+ )
264
+
265
+ return success, sorted(
266
+ [
267
+ filename
268
+ for filename in [
269
+ filename.split(f"{env.WEBDAV_LOGIN}/{object_name}/", 1)[1]
270
+ for filename in list_of_files
271
+ if not filename.endswith("/")
272
+ ]
273
+ if filename
274
+ ]
275
+ )
276
+
277
+ return super().ls(
278
+ object_name=object_name,
279
+ where=where,
280
+ )
281
+
282
+ def upload(
283
+ self,
284
+ object_name: str,
285
+ filename: str = "",
286
+ public: bool = False,
287
+ zip: bool = False,
288
+ log: bool = True,
289
+ ) -> bool:
290
+ if public or zip:
291
+ logger.error("public/zip upload not supported.")
292
+ return False
293
+
294
+ if filename:
295
+ if not self.mkdir(
296
+ path="{}/{}".format(
297
+ object_name,
298
+ file.path(filename),
299
+ ),
300
+ log=log,
301
+ ):
302
+ return False
303
+
304
+ url = f"{env.WEBDAV_HOSTNAME}/{object_name}/{filename}"
305
+
306
+ local_path = objects.path_of(
307
+ object_name=object_name,
308
+ filename=filename,
309
+ )
310
+
311
+ try:
312
+ with open(local_path, "rb") as file_data:
313
+ response = requests.put(
314
+ url,
315
+ data=file_data,
316
+ auth=HTTPBasicAuth(
317
+ env.WEBDAV_LOGIN,
318
+ env.WEBDAV_PASSWORD,
319
+ ),
320
+ )
321
+ except Exception as e:
322
+ logger.error(e)
323
+ return False
324
+
325
+ if response.status_code in [200, 201, 204]:
326
+ return super().upload(
327
+ object_name=object_name,
328
+ filename=filename,
329
+ public=public,
330
+ zip=zip,
331
+ log=log,
332
+ )
333
+
334
+ logger.error(f"failed to upload: {response.status_code} - {response.text}")
335
+ return False
336
+
337
+ object_path = "{}/".format(objects.object_path(object_name=object_name))
338
+ for filename_ in tqdm(
339
+ sorted(
340
+ glob.glob(
341
+ objects.path_of(
342
+ object_name=object_name,
343
+ filename="**",
344
+ ),
345
+ recursive=True,
346
+ )
347
+ )
348
+ ):
349
+ if not file.exists(filename_):
350
+ continue
351
+
352
+ if not self.upload(
353
+ object_name=object_name,
354
+ filename=filename_.split(object_path, 1)[1],
355
+ public=public,
356
+ log=log,
357
+ ):
358
+ return False
359
+
360
+ return True
@@ -5,15 +5,16 @@ from webdav3.client import Client
5
5
  from tqdm import tqdm
6
6
 
7
7
  from bluer_objects.storage.base import StorageInterface
8
- from bluer_objects import env, file, path
8
+ from bluer_objects import env
9
9
  from bluer_objects import objects
10
- from bluer_objects.host import zip, unzip
10
+ from bluer_objects.host import unzip
11
+ from bluer_objects.storage.policies import DownloadPolicy
11
12
  from bluer_objects.logger import logger
12
13
 
13
14
 
14
15
  # tars the objects to avoid 'content-length' - see WebDAVInterface.
15
16
  class WebDAVzipInterface(StorageInterface):
16
- name = "webdavzip"
17
+ name = "webdav-zip"
17
18
 
18
19
  def __init__(self):
19
20
  super().__init__()
@@ -29,13 +30,15 @@ class WebDAVzipInterface(StorageInterface):
29
30
  def clear(
30
31
  self,
31
32
  do_dryrun: bool = True,
33
+ log: bool = True,
34
+ public: bool = False,
32
35
  ) -> bool:
33
- logger.info(
34
- "{}.clear({})".format(
35
- self.__class__.__name__,
36
- "dryrun" if do_dryrun else "",
37
- )
38
- )
36
+ if not super().clear(
37
+ do_dryrun=do_dryrun,
38
+ log=log,
39
+ public=public,
40
+ ):
41
+ return False
39
42
 
40
43
  count: int = 0
41
44
  for thing in tqdm(self.client.list()):
@@ -65,6 +68,7 @@ class WebDAVzipInterface(StorageInterface):
65
68
  object_name: str,
66
69
  filename: str = "",
67
70
  log: bool = True,
71
+ policy: DownloadPolicy = DownloadPolicy.NONE,
68
72
  ) -> bool:
69
73
  object_path = objects.object_path(
70
74
  object_name=object_name,
@@ -99,6 +103,7 @@ class WebDAVzipInterface(StorageInterface):
99
103
  return super().download(
100
104
  object_name=object_name,
101
105
  log=log,
106
+ policy=policy,
102
107
  )
103
108
 
104
109
  def ls(
@@ -106,24 +111,6 @@ class WebDAVzipInterface(StorageInterface):
106
111
  object_name: str,
107
112
  where: str = "local",
108
113
  ) -> Tuple[bool, List[str]]:
109
- if where == "local":
110
- object_path = objects.object_path(
111
- object_name=object_name,
112
- )
113
-
114
- return True, [
115
- os.path.relpath(filename, start=object_path)
116
- for filename in glob.glob(
117
- os.path.join(
118
- object_path,
119
- "**",
120
- "*",
121
- ),
122
- recursive=True,
123
- )
124
- if os.path.isfile(filename)
125
- ]
126
-
127
114
  if where == "cloud":
128
115
  try:
129
116
  if self.client.check(remote_path=f"{object_name}.zip"):
@@ -134,15 +121,23 @@ class WebDAVzipInterface(StorageInterface):
134
121
 
135
122
  return True, []
136
123
 
137
- logger.error(f"Unknown 'where': {where}")
138
- return False, []
124
+ return super().ls(
125
+ object_name=object_name,
126
+ where=where,
127
+ )
139
128
 
140
129
  def upload(
141
130
  self,
142
131
  object_name: str,
143
132
  filename: str = "",
133
+ public: bool = False,
134
+ zip: bool = False,
144
135
  log: bool = True,
145
136
  ) -> bool:
137
+ if public or zip:
138
+ logger.error("public/zip upload not supported.")
139
+ return False
140
+
146
141
  object_path = objects.object_path(object_name=object_name)
147
142
 
148
143
  if not zip(
@@ -165,5 +160,7 @@ class WebDAVzipInterface(StorageInterface):
165
160
 
166
161
  return super().upload(
167
162
  object_name=object_name,
163
+ public=public,
164
+ zip=zip,
168
165
  log=log,
169
166
  )
@@ -1,15 +1,22 @@
1
1
  from typing import Tuple, List
2
2
 
3
+ from bluer_objects.storage.s3 import S3Interface
3
4
  from bluer_objects.storage.base import StorageInterface
4
5
  from bluer_objects.storage.WebDAV import WebDAVInterface
6
+ from bluer_objects.storage.WebDAVrequest import WebDAVRequestInterface
5
7
  from bluer_objects.storage.WebDAVzip import WebDAVzipInterface
8
+ from bluer_objects.storage.policies import DownloadPolicy
6
9
  from bluer_objects import env
7
10
  from bluer_objects.logger import logger
8
11
 
9
12
  interface = StorageInterface()
10
13
 
11
- if env.BLUER_OBJECTS_STORAGE_INTERFACE == WebDAVInterface.name:
14
+ if env.BLUER_OBJECTS_STORAGE_INTERFACE == S3Interface.name:
15
+ interface = S3Interface()
16
+ elif env.BLUER_OBJECTS_STORAGE_INTERFACE == WebDAVInterface.name:
12
17
  interface = WebDAVInterface()
18
+ elif env.BLUER_OBJECTS_STORAGE_INTERFACE == WebDAVRequestInterface.name:
19
+ interface = WebDAVRequestInterface()
13
20
  elif env.BLUER_OBJECTS_STORAGE_INTERFACE == WebDAVzipInterface.name:
14
21
  interface = WebDAVzipInterface()
15
22
  else:
@@ -19,9 +26,13 @@ else:
19
26
 
20
27
  def clear(
21
28
  do_dryrun: bool = True,
29
+ log: bool = True,
30
+ public: bool = False,
22
31
  ) -> bool:
23
32
  return interface.clear(
24
33
  do_dryrun=do_dryrun,
34
+ log=log,
35
+ public=public,
25
36
  )
26
37
 
27
38
 
@@ -29,11 +40,13 @@ def download(
29
40
  object_name: str,
30
41
  filename: str = "",
31
42
  log: bool = True,
43
+ policy: DownloadPolicy = DownloadPolicy.NONE,
32
44
  ) -> bool:
33
45
  return interface.download(
34
46
  object_name=object_name,
35
47
  filename=filename,
36
48
  log=log,
49
+ policy=policy,
37
50
  )
38
51
 
39
52
 
@@ -47,13 +60,27 @@ def ls(
47
60
  )
48
61
 
49
62
 
63
+ def ls_objects(
64
+ prefix: str,
65
+ where: str = "local",
66
+ ) -> Tuple[bool, List[str]]:
67
+ return interface.ls_objects(
68
+ prefix=prefix,
69
+ where=where,
70
+ )
71
+
72
+
50
73
  def upload(
51
74
  object_name: str,
52
75
  filename: str = "",
76
+ public: bool = False,
77
+ zip: bool = False,
53
78
  log: bool = True,
54
79
  ) -> bool:
55
80
  return interface.upload(
56
81
  object_name=object_name,
57
82
  filename=filename,
83
+ public=public,
84
+ zip=zip,
58
85
  log=log,
59
86
  )