bluer-objects 6.25.1__py3-none-any.whl → 6.27.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.

Potentially problematic release.


This version of bluer-objects might be problematic. Click here for more details.

Files changed (40) hide show
  1. bluer_objects/.abcli/alias.sh +3 -3
  2. bluer_objects/.abcli/clone.sh +6 -6
  3. bluer_objects/.abcli/download.sh +11 -42
  4. bluer_objects/.abcli/gif.sh +2 -2
  5. bluer_objects/.abcli/mlflow.sh +1 -1
  6. bluer_objects/.abcli/publish.sh +3 -3
  7. bluer_objects/.abcli/tests/ls.sh +1 -1
  8. bluer_objects/.abcli/tests/storage.sh +60 -0
  9. bluer_objects/.abcli/upload.sh +8 -60
  10. bluer_objects/__init__.py +1 -1
  11. bluer_objects/config.env +3 -1
  12. bluer_objects/env.py +6 -1
  13. bluer_objects/file/__main__.py +15 -2
  14. bluer_objects/help/download.py +23 -0
  15. bluer_objects/help/functions.py +10 -1
  16. bluer_objects/help/upload.py +20 -0
  17. bluer_objects/host/__init__.py +12 -1
  18. bluer_objects/host/__main__.py +0 -1
  19. bluer_objects/host/functions.py +14 -1
  20. bluer_objects/metadata/get.py +2 -2
  21. bluer_objects/metadata/post.py +2 -1
  22. bluer_objects/sample.env +3 -16
  23. bluer_objects/storage/WebDAV.py +114 -0
  24. bluer_objects/storage/WebDAVzip.py +84 -0
  25. bluer_objects/storage/__init__.py +39 -0
  26. bluer_objects/storage/__main__.py +44 -0
  27. bluer_objects/storage/base.py +37 -0
  28. bluer_objects/tests/test_download.py +52 -0
  29. bluer_objects/tests/test_env.py +11 -0
  30. bluer_objects/tests/test_graphics.py +2 -1
  31. bluer_objects/tests/test_graphics_gif.py +2 -1
  32. bluer_objects/tests/test_objects.py +2 -116
  33. bluer_objects/tests/test_upload.py +76 -0
  34. {bluer_objects-6.25.1.dist-info → bluer_objects-6.27.1.dist-info}/METADATA +4 -3
  35. {bluer_objects-6.25.1.dist-info → bluer_objects-6.27.1.dist-info}/RECORD +39 -30
  36. bluer_objects/.abcli/tags.sh +0 -5
  37. /bluer_objects/.abcli/tests/{test_gif.sh → gif.sh} +0 -0
  38. {bluer_objects-6.25.1.dist-info → bluer_objects-6.27.1.dist-info}/WHEEL +0 -0
  39. {bluer_objects-6.25.1.dist-info → bluer_objects-6.27.1.dist-info}/licenses/LICENSE +0 -0
  40. {bluer_objects-6.25.1.dist-info → bluer_objects-6.27.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,84 @@
1
+ from webdav3.client import Client
2
+
3
+ from bluer_objects.storage.base import StorageInterface
4
+ from bluer_objects import env, file, path
5
+ from bluer_objects import objects
6
+ from bluer_objects.host import zip, unzip
7
+ from bluer_objects.logger import logger
8
+
9
+
10
+ # tars the objects to avoid 'content-length' - see WebDAVInterface.
11
+ class WebDAVzipInterface(StorageInterface):
12
+ name = "webdavzip"
13
+
14
+ def __init__(self):
15
+ super().__init__()
16
+
17
+ config = {
18
+ "webdav_hostname": env.WEBDAV_HOSTNAME,
19
+ "webdav_login": env.WEBDAV_LOGIN,
20
+ "webdav_password": env.WEBDAV_PASSWORD,
21
+ }
22
+
23
+ self.client = Client(config)
24
+
25
+ def download(
26
+ self,
27
+ object_name: str,
28
+ filename: str = "",
29
+ log: bool = True,
30
+ ) -> bool:
31
+ object_path = objects.object_path(object_name=object_name)
32
+ zip_filename = f"{object_path}.zip"
33
+
34
+ try:
35
+ self.client.download_sync(
36
+ remote_path=f"{object_name}.zip",
37
+ local_path=zip_filename,
38
+ )
39
+ except Exception as e:
40
+ logger.error(e)
41
+ return False
42
+
43
+ if not unzip(
44
+ zip_filename=zip_filename,
45
+ output_folder=object_path,
46
+ log=log,
47
+ ):
48
+ return False
49
+
50
+ return super().download(
51
+ object_name=object_name,
52
+ log=log,
53
+ )
54
+
55
+ def upload(
56
+ self,
57
+ object_name: str,
58
+ filename: str = "",
59
+ log: bool = True,
60
+ ) -> bool:
61
+ object_path = objects.object_path(object_name=object_name)
62
+
63
+ if not zip(
64
+ zip_filename=f"../{object_name}.zip",
65
+ input_folder=".",
66
+ work_dir=object_path,
67
+ log=log,
68
+ ):
69
+ return False
70
+
71
+ zip_filename = f"{object_path}.zip"
72
+ try:
73
+ self.client.upload_sync(
74
+ remote_path=f"{object_name}.zip",
75
+ local_path=zip_filename,
76
+ )
77
+ except Exception as e:
78
+ logger.error(e)
79
+ return False
80
+
81
+ return super().upload(
82
+ object_name=object_name,
83
+ log=log,
84
+ )
@@ -0,0 +1,39 @@
1
+ from bluer_objects.storage.base import StorageInterface
2
+ from bluer_objects.storage.WebDAV import WebDAVInterface
3
+ from bluer_objects.storage.WebDAVzip import WebDAVzipInterface
4
+ from bluer_objects import env
5
+ from bluer_objects.logger import logger
6
+
7
+ interface = StorageInterface()
8
+
9
+ if env.BLUER_OBJECTS_STORAGE_INTERFACE == WebDAVInterface.name:
10
+ interface = WebDAVInterface()
11
+ elif env.BLUER_OBJECTS_STORAGE_INTERFACE == WebDAVzipInterface.name:
12
+ interface = WebDAVzipInterface()
13
+ else:
14
+ logger.error(f"{env.BLUER_OBJECTS_STORAGE_INTERFACE}: interface not found.")
15
+ assert False
16
+
17
+
18
+ def download(
19
+ object_name: str,
20
+ filename: str = "",
21
+ log: bool = True,
22
+ ) -> bool:
23
+ return interface.download(
24
+ object_name=object_name,
25
+ filename=filename,
26
+ log=log,
27
+ )
28
+
29
+
30
+ def upload(
31
+ object_name: str,
32
+ filename: str = "",
33
+ log: bool = True,
34
+ ) -> bool:
35
+ return interface.upload(
36
+ object_name=object_name,
37
+ filename=filename,
38
+ log=log,
39
+ )
@@ -0,0 +1,44 @@
1
+ import argparse
2
+
3
+ from blueness import module
4
+ from blueness.argparse.generic import sys_exit
5
+
6
+ from bluer_objects import NAME
7
+ from bluer_objects import storage
8
+ from bluer_objects.logger import logger
9
+
10
+ NAME = module.name(__file__, NAME)
11
+
12
+ parser = argparse.ArgumentParser(NAME)
13
+ parser.add_argument(
14
+ "task",
15
+ type=str,
16
+ help="download | upload",
17
+ )
18
+ parser.add_argument(
19
+ "--object_name",
20
+ type=str,
21
+ )
22
+ parser.add_argument(
23
+ "--filename",
24
+ type=str,
25
+ default="",
26
+ )
27
+ args = parser.parse_args()
28
+
29
+
30
+ success = False
31
+ if args.task == "download":
32
+ success = storage.download(
33
+ object_name=args.object_name,
34
+ filename=args.filename,
35
+ )
36
+ elif args.task == "upload":
37
+ success = storage.upload(
38
+ object_name=args.object_name,
39
+ filename=args.filename,
40
+ )
41
+ else:
42
+ success = None
43
+
44
+ sys_exit(logger, NAME, args.task, success)
@@ -0,0 +1,37 @@
1
+ from bluer_objects.logger import logger
2
+
3
+
4
+ class StorageInterface:
5
+ def download(
6
+ self,
7
+ object_name: str,
8
+ filename: str = "",
9
+ log: bool = True,
10
+ ) -> bool:
11
+ if log:
12
+ logger.info(
13
+ "{}.download {}{}".format(
14
+ self.__class__.__name__,
15
+ object_name,
16
+ f"/{filename}" if filename else "",
17
+ )
18
+ )
19
+
20
+ return True
21
+
22
+ def upload(
23
+ self,
24
+ object_name: str,
25
+ filename: str = "",
26
+ log: bool = True,
27
+ ) -> bool:
28
+ if log:
29
+ logger.info(
30
+ "{}.upload {}{}".format(
31
+ self.__class__.__name__,
32
+ object_name,
33
+ f"/{filename}" if filename else "",
34
+ )
35
+ )
36
+
37
+ return True
@@ -0,0 +1,52 @@
1
+ import pytest
2
+
3
+
4
+ from bluer_objects import file, objects
5
+ from bluer_objects import storage
6
+
7
+
8
+ @pytest.mark.parametrize(
9
+ ["object_name", "filename"],
10
+ [[VANWATCH_TEST_OBJECT, "vancouver.geojson"]],
11
+ )
12
+ def test_objects_download(
13
+ object_name: str,
14
+ filename: str,
15
+ ):
16
+ filename_fullpath = objects.path_of(
17
+ filename=filename,
18
+ object_name=object_name,
19
+ )
20
+ if file.exists(filename_fullpath):
21
+ assert file.delete(filename_fullpath)
22
+
23
+ assert not file.exists(filename_fullpath)
24
+
25
+ assert objects.storage(object_name=object_name)
26
+
27
+ assert file.exists(filename_fullpath)
28
+
29
+
30
+ @pytest.mark.parametrize(
31
+ ["object_name", "filename"],
32
+ [[VANWATCH_TEST_OBJECT, "vancouver.geojson"]],
33
+ )
34
+ def test_objects_download_filename(
35
+ object_name: str,
36
+ filename: str,
37
+ ):
38
+ filename_fullpath = objects.path_of(
39
+ filename=filename,
40
+ object_name=object_name,
41
+ )
42
+ if file.exists(filename_fullpath):
43
+ assert file.delete(filename_fullpath)
44
+
45
+ assert not file.exists(filename_fullpath)
46
+
47
+ assert storage.download(
48
+ object_name=object_name,
49
+ filename=filename,
50
+ )
51
+
52
+ assert file.exists(filename_fullpath)
@@ -1,6 +1,8 @@
1
1
  from bluer_ai.tests.test_env import test_bluer_ai_env
2
2
 
3
3
  from bluer_objects import env
4
+ from bluer_objects.storage.WebDAV import WebDAVInterface
5
+ from bluer_objects.storage.WebDAVzip import WebDAVzipInterface
4
6
 
5
7
 
6
8
  def test_required_env():
@@ -15,3 +17,12 @@ def test_bluer_objects_env():
15
17
  assert env.DATABRICKS_TOKEN
16
18
 
17
19
  assert env.ABCLI_MLFLOW_EXPERIMENT_PREFIX
20
+
21
+ assert env.BLUER_OBJECTS_STORAGE_INTERFACE in [
22
+ WebDAVInterface.name,
23
+ WebDAVzipInterface.name,
24
+ ]
25
+
26
+ assert env.WEBDAV_HOSTNAME
27
+ assert env.WEBDAV_LOGIN
28
+ assert env.WEBDAV_PASSWORD
@@ -3,6 +3,7 @@ import pytest
3
3
  from blueness import module
4
4
 
5
5
  from bluer_objects import file, objects, NAME
6
+ from bluer_objects import storage
6
7
  from bluer_objects.env import VANWATCH_TEST_OBJECT
7
8
  from bluer_objects.logger import logger
8
9
 
@@ -13,7 +14,7 @@ NAME = module.name(__file__, NAME)
13
14
  def test_image():
14
15
  object_name = VANWATCH_TEST_OBJECT
15
16
 
16
- assert objects.download(object_name)
17
+ assert storage.download(object_name)
17
18
 
18
19
  success, matrix = file.load_image(
19
20
  objects.path_of(
@@ -2,6 +2,7 @@ import pytest
2
2
  import glob
3
3
 
4
4
  from bluer_objects import objects
5
+ from bluer_objects import storage
5
6
  from bluer_objects.graphics.gif import generate_animated_gif
6
7
 
7
8
 
@@ -16,7 +17,7 @@ def test_graphics_gif_generate_animated_gif(
16
17
  object_name: str,
17
18
  scale: int,
18
19
  ):
19
- assert objects.download(object_name)
20
+ assert storage.download(object_name)
20
21
 
21
22
  list_of_images = list(glob.glob(objects.path_of("*.png", object_name)))
22
23
  if object_name != "void":
@@ -3,6 +3,7 @@ import pytest
3
3
  from blueness import module
4
4
 
5
5
  from bluer_objects import file, path, objects, NAME
6
+ from bluer_objects import storage
6
7
  from bluer_objects.env import VANWATCH_TEST_OBJECT
7
8
  from bluer_objects.logger import logger
8
9
 
@@ -13,60 +14,13 @@ NAME = module.name(__file__, NAME)
13
14
  def test_object():
14
15
  object_name = VANWATCH_TEST_OBJECT
15
16
 
16
- assert objects.download(object_name=object_name)
17
+ assert storage.download(object_name=object_name)
17
18
 
18
19
  yield object_name
19
20
 
20
21
  logger.info(f"deleting {NAME}.test_object ...")
21
22
 
22
23
 
23
- @pytest.mark.parametrize(
24
- ["object_name", "filename"],
25
- [[VANWATCH_TEST_OBJECT, "vancouver.geojson"]],
26
- )
27
- def test_objects_download(
28
- object_name: str,
29
- filename: str,
30
- ):
31
- filename_fullpath = objects.path_of(
32
- filename=filename,
33
- object_name=object_name,
34
- )
35
- if file.exists(filename_fullpath):
36
- assert file.delete(filename_fullpath)
37
-
38
- assert not file.exists(filename_fullpath)
39
-
40
- assert objects.download(object_name=object_name)
41
-
42
- assert file.exists(filename_fullpath)
43
-
44
-
45
- @pytest.mark.parametrize(
46
- ["object_name", "filename"],
47
- [[VANWATCH_TEST_OBJECT, "vancouver.geojson"]],
48
- )
49
- def test_objects_download_filename(
50
- object_name: str,
51
- filename: str,
52
- ):
53
- filename_fullpath = objects.path_of(
54
- filename=filename,
55
- object_name=object_name,
56
- )
57
- if file.exists(filename_fullpath):
58
- assert file.delete(filename_fullpath)
59
-
60
- assert not file.exists(filename_fullpath)
61
-
62
- assert objects.download(
63
- object_name=object_name,
64
- filename=filename,
65
- )
66
-
67
- assert file.exists(filename_fullpath)
68
-
69
-
70
24
  @pytest.mark.parametrize(
71
25
  ["cloud"],
72
26
  [[True], [False]],
@@ -110,71 +64,3 @@ def test_objects_unique_object(prefix: str):
110
64
  object_name = objects.unique_object(prefix)
111
65
  assert object_name
112
66
  assert object_name.startswith(prefix)
113
-
114
-
115
- @pytest.mark.parametrize(
116
- ["filename"],
117
- [["vancouver.geojson"]],
118
- )
119
- def test_objects_upload(
120
- filename: str,
121
- ):
122
- assert objects.download(object_name=VANWATCH_TEST_OBJECT)
123
-
124
- object_name = objects.unique_object("test_objects_upload_filename")
125
-
126
- source_filename = objects.path_of(
127
- filename=filename,
128
- object_name=VANWATCH_TEST_OBJECT,
129
- )
130
- destination_filename = objects.path_of(
131
- filename=filename,
132
- object_name=object_name,
133
- )
134
- assert file.copy(source_filename, destination_filename)
135
-
136
- assert objects.upload(object_name=object_name)
137
-
138
- assert file.delete(destination_filename)
139
- assert not file.exists(destination_filename)
140
-
141
- assert objects.download(object_name=object_name)
142
-
143
- assert file.exists(destination_filename)
144
-
145
-
146
- @pytest.mark.parametrize(
147
- ["filename"],
148
- [["vancouver.geojson"]],
149
- )
150
- def test_objects_upload_filename(
151
- filename: str,
152
- ):
153
- assert objects.download(object_name=VANWATCH_TEST_OBJECT)
154
-
155
- object_name = objects.unique_object("test_objects_upload_filename")
156
-
157
- source_filename = objects.path_of(
158
- filename=filename,
159
- object_name=VANWATCH_TEST_OBJECT,
160
- )
161
- destination_filename = objects.path_of(
162
- filename=filename,
163
- object_name=object_name,
164
- )
165
- assert file.copy(source_filename, destination_filename)
166
-
167
- assert objects.upload(
168
- object_name=object_name,
169
- filename=filename,
170
- )
171
-
172
- assert file.delete(destination_filename)
173
- assert not file.exists(destination_filename)
174
-
175
- assert objects.download(
176
- object_name=object_name,
177
- filename=filename,
178
- )
179
-
180
- assert file.exists(destination_filename)
@@ -0,0 +1,76 @@
1
+ import pytest
2
+
3
+ from blueness import module
4
+
5
+ from bluer_objects import file, objects, NAME
6
+ from bluer_objects import storage
7
+
8
+ NAME = module.name(__file__, NAME)
9
+
10
+
11
+ @pytest.mark.parametrize(
12
+ ["filename"],
13
+ [["vancouver.geojson"]],
14
+ )
15
+ def test_objects_upload(
16
+ filename: str,
17
+ ):
18
+ assert storage.download(object_name=VANWATCH_TEST_OBJECT)
19
+
20
+ object_name = objects.unique_object("test_objects_upload_filename")
21
+
22
+ source_filename = objects.path_of(
23
+ filename=filename,
24
+ object_name=VANWATCH_TEST_OBJECT,
25
+ )
26
+ destination_filename = objects.path_of(
27
+ filename=filename,
28
+ object_name=object_name,
29
+ )
30
+ assert file.copy(source_filename, destination_filename)
31
+
32
+ assert objects.upload(object_name=object_name)
33
+
34
+ assert file.delete(destination_filename)
35
+ assert not file.exists(destination_filename)
36
+
37
+ assert storage.download(object_name=object_name)
38
+
39
+ assert file.exists(destination_filename)
40
+
41
+
42
+ @pytest.mark.parametrize(
43
+ ["filename"],
44
+ [["vancouver.geojson"]],
45
+ )
46
+ def test_objects_upload_filename(
47
+ filename: str,
48
+ ):
49
+ assert storage.download(object_name=VANWATCH_TEST_OBJECT)
50
+
51
+ object_name = objects.unique_object("test_objects_upload_filename")
52
+
53
+ source_filename = objects.path_of(
54
+ filename=filename,
55
+ object_name=VANWATCH_TEST_OBJECT,
56
+ )
57
+ destination_filename = objects.path_of(
58
+ filename=filename,
59
+ object_name=object_name,
60
+ )
61
+ assert file.copy(source_filename, destination_filename)
62
+
63
+ assert objects.upload(
64
+ object_name=object_name,
65
+ filename=filename,
66
+ )
67
+
68
+ assert file.delete(destination_filename)
69
+ assert not file.exists(destination_filename)
70
+
71
+ assert storage.download(
72
+ object_name=object_name,
73
+ filename=filename,
74
+ )
75
+
76
+ assert file.exists(destination_filename)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bluer_objects
3
- Version: 6.25.1
3
+ Version: 6.27.1
4
4
  Summary: 🌀 data objects for Bash.
5
5
  Home-page: https://github.com/kamangir/bluer-objects
6
6
  Author: Arash Abadpour (Kamangir)
@@ -13,6 +13,7 @@ Classifier: Operating System :: OS Independent
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
15
  Requires-Dist: bluer_ai
16
+ Requires-Dist: webdavclient3
16
17
  Requires-Dist: dill
17
18
  Requires-Dist: mlflow
18
19
  Requires-Dist: pandas
@@ -33,7 +34,7 @@ Dynamic: summary
33
34
 
34
35
  # 🌀 bluer-objects
35
36
 
36
- 🌀 `bluer-objects` are the inputs and outputs of [AI algo](https://github.com/kamangir/giza). They are maintained in cloud storage and their metadata is tracked by [MLflow](https://mlflow.org/).
37
+ 🌀 `bluer-objects` are the inputs and outputs of [AI algo](https://github.com/kamangir/giza). They are maintained in cloud storage (supports [WebDav](https://pypi.org/project/webdavclient3/)) and their metadata is tracked by [MLflow](https://mlflow.org/).
37
38
 
38
39
  For example, the Sentinel-2 [datacube](https://github.com/kamangir/blue-geo/tree/main/blue_geo/datacube) `datacube-EarthSearch-sentinel_2_l1c-S2A_10UDC_20240731_0_L1C` and 🌐 [`@geo watch` outputs](https://github.com/kamangir/blue-geo/tree/main/blue_geo/watch) are `bluer-objects`.
39
40
 
@@ -52,6 +53,6 @@ Also home to [blue README](https://github.com/kamangir/bluer-objects/blob/main/b
52
53
 
53
54
  [![pylint](https://github.com/kamangir/bluer-objects/actions/workflows/pylint.yml/badge.svg)](https://github.com/kamangir/bluer-objects/actions/workflows/pylint.yml) [![pytest](https://github.com/kamangir/bluer-objects/actions/workflows/pytest.yml/badge.svg)](https://github.com/kamangir/bluer-objects/actions/workflows/pytest.yml) [![bashtest](https://github.com/kamangir/bluer-objects/actions/workflows/bashtest.yml/badge.svg)](https://github.com/kamangir/bluer-objects/actions/workflows/bashtest.yml) [![PyPI version](https://img.shields.io/pypi/v/bluer-objects.svg)](https://pypi.org/project/bluer-objects/) [![PyPI - Downloads](https://img.shields.io/pypi/dd/bluer-objects)](https://pypistats.org/packages/bluer-objects)
54
55
 
55
- built by 🌀 [`bluer_options-5.24.1`](https://github.com/kamangir/awesome-bash-cli), based on 🌀 [`bluer_objects-6.25.1`](https://github.com/kamangir/bluer-objects).
56
+ built by 🌀 [`bluer_options-5.26.1`](https://github.com/kamangir/awesome-bash-cli), based on 🌀 [`bluer_objects-6.27.1`](https://github.com/kamangir/bluer-objects).
56
57
 
57
58
  built by 🌀 [`blueness-3.96.1`](https://github.com/kamangir/blueness).