bluer-objects 6.104.1__py3-none-any.whl → 6.377.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 (146) hide show
  1. bluer_objects/.abcli/abcli.sh +6 -0
  2. bluer_objects/.abcli/alias.sh +11 -0
  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 +37 -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.sh +0 -2
  22. bluer_objects/.abcli/pdf/convert.sh +92 -0
  23. bluer_objects/.abcli/pdf.sh +15 -0
  24. bluer_objects/.abcli/storage/clear.sh +2 -0
  25. bluer_objects/.abcli/tests/clone.sh +2 -3
  26. bluer_objects/.abcli/tests/create_test_asset.sh +16 -0
  27. bluer_objects/.abcli/tests/file.sh +64 -0
  28. bluer_objects/.abcli/tests/gif.sh +3 -3
  29. bluer_objects/.abcli/tests/help.sh +27 -4
  30. bluer_objects/.abcli/tests/ls.sh +11 -4
  31. bluer_objects/.abcli/tests/metadata.sh +35 -0
  32. bluer_objects/.abcli/tests/mlflow_lock.sh +30 -0
  33. bluer_objects/.abcli/tests/open.sh +11 -0
  34. bluer_objects/.abcli/tests/open_gif_open.sh +14 -0
  35. bluer_objects/.abcli/tests/pdf.sh +31 -0
  36. bluer_objects/.abcli/tests/storage_clear.sh +11 -0
  37. bluer_objects/.abcli/tests/storage_public_upload.sh +25 -0
  38. bluer_objects/.abcli/tests/storage_status.sh +12 -0
  39. bluer_objects/.abcli/tests/{storage.sh → storage_upload_download.sh} +26 -8
  40. bluer_objects/.abcli/tests/web_is_accessible.sh +17 -0
  41. bluer_objects/.abcli/tests/web_where_am_ai.sh +5 -0
  42. bluer_objects/.abcli/upload.sh +26 -2
  43. bluer_objects/.abcli/url.sh +15 -0
  44. bluer_objects/.abcli/web/is_accessible.sh +13 -0
  45. bluer_objects/.abcli/web/where_am_i.sh +5 -0
  46. bluer_objects/README/__init__.py +24 -9
  47. bluer_objects/README/alias.py +56 -0
  48. bluer_objects/README/consts.py +39 -0
  49. bluer_objects/README/functions.py +127 -205
  50. bluer_objects/README/items.py +78 -6
  51. bluer_objects/README/utils.py +275 -0
  52. bluer_objects/__init__.py +1 -1
  53. bluer_objects/assets/__init__.py +0 -0
  54. bluer_objects/assets/__main__.py +57 -0
  55. bluer_objects/assets/functions.py +62 -0
  56. bluer_objects/config.env +9 -1
  57. bluer_objects/env.py +23 -0
  58. bluer_objects/file/__main__.py +52 -7
  59. bluer_objects/file/functions.py +13 -3
  60. bluer_objects/file/load.py +2 -9
  61. bluer_objects/file/save.py +17 -24
  62. bluer_objects/graphics/__main__.py +7 -0
  63. bluer_objects/graphics/gif.py +11 -7
  64. bluer_objects/graphics/screen.py +9 -8
  65. bluer_objects/help/assets.py +96 -0
  66. bluer_objects/help/create_test_asset.py +22 -0
  67. bluer_objects/help/download.py +17 -3
  68. bluer_objects/help/file.py +59 -0
  69. bluer_objects/help/functions.py +11 -1
  70. bluer_objects/help/gif.py +25 -0
  71. bluer_objects/help/host.py +6 -4
  72. bluer_objects/help/ls.py +26 -3
  73. bluer_objects/help/metadata.py +51 -0
  74. bluer_objects/help/mlflow/__init__.py +23 -2
  75. bluer_objects/help/mlflow/lock.py +52 -0
  76. bluer_objects/help/pdf.py +67 -0
  77. bluer_objects/help/upload.py +10 -3
  78. bluer_objects/help/web.py +38 -0
  79. bluer_objects/host/functions.py +4 -1
  80. bluer_objects/logger/confusion_matrix.py +76 -0
  81. bluer_objects/logger/image.py +110 -0
  82. bluer_objects/logger/stitch.py +107 -0
  83. bluer_objects/markdown.py +8 -6
  84. bluer_objects/metadata/__init__.py +1 -0
  85. bluer_objects/metadata/flatten.py +27 -0
  86. bluer_objects/mlflow/lock/__init__.py +1 -0
  87. bluer_objects/mlflow/lock/__main__.py +58 -0
  88. bluer_objects/mlflow/lock/functions.py +121 -0
  89. bluer_objects/mlflow/logging.py +47 -41
  90. bluer_objects/pdf/__init__.py +1 -0
  91. bluer_objects/pdf/__main__.py +78 -0
  92. bluer_objects/pdf/convert/__init__.py +0 -0
  93. bluer_objects/pdf/convert/batch.py +54 -0
  94. bluer_objects/pdf/convert/combination.py +32 -0
  95. bluer_objects/pdf/convert/convert.py +111 -0
  96. bluer_objects/pdf/convert/image.py +53 -0
  97. bluer_objects/pdf/convert/md.py +97 -0
  98. bluer_objects/pdf/convert/missing.py +96 -0
  99. bluer_objects/pdf/convert/pdf.py +37 -0
  100. bluer_objects/sample.env +6 -0
  101. bluer_objects/storage/WebDAV.py +11 -7
  102. bluer_objects/storage/WebDAVrequest.py +360 -0
  103. bluer_objects/storage/WebDAVzip.py +26 -29
  104. bluer_objects/storage/__init__.py +28 -1
  105. bluer_objects/storage/__main__.py +40 -6
  106. bluer_objects/storage/base.py +84 -5
  107. bluer_objects/storage/policies.py +7 -0
  108. bluer_objects/storage/s3.py +367 -0
  109. bluer_objects/testing/__main__.py +6 -0
  110. bluer_objects/tests/test_README_consts.py +71 -0
  111. bluer_objects/tests/test_README_items.py +128 -0
  112. bluer_objects/tests/test_alias.py +33 -0
  113. bluer_objects/tests/test_env.py +25 -2
  114. bluer_objects/tests/test_file_download.py +25 -0
  115. bluer_objects/tests/test_file_load_save.py +1 -2
  116. bluer_objects/tests/test_file_load_save_text.py +46 -0
  117. bluer_objects/tests/test_graphics_gif.py +2 -0
  118. bluer_objects/tests/test_log_image_grid.py +29 -0
  119. bluer_objects/tests/test_logger_confusion_matrix.py +18 -0
  120. bluer_objects/tests/test_logger_matrix.py +2 -2
  121. bluer_objects/tests/test_logger_stitch_images.py +47 -0
  122. bluer_objects/tests/test_metadata.py +12 -6
  123. bluer_objects/tests/test_metadata_flatten.py +109 -0
  124. bluer_objects/tests/test_mlflow.py +2 -2
  125. bluer_objects/tests/test_mlflow_lock.py +26 -0
  126. bluer_objects/tests/test_objects.py +2 -0
  127. bluer_objects/tests/test_shell.py +34 -0
  128. bluer_objects/tests/test_storage.py +8 -21
  129. bluer_objects/tests/test_storage_base.py +39 -0
  130. bluer_objects/tests/test_storage_s3.py +67 -0
  131. bluer_objects/tests/test_storage_webdav_request.py +75 -0
  132. bluer_objects/tests/test_storage_webdav_zip.py +42 -0
  133. bluer_objects/tests/test_web_is_accessible.py +11 -0
  134. bluer_objects/web/__init__.py +1 -0
  135. bluer_objects/web/__main__.py +31 -0
  136. bluer_objects/web/functions.py +9 -0
  137. {bluer_objects-6.104.1.dist-info → bluer_objects-6.377.1.dist-info}/METADATA +6 -3
  138. bluer_objects-6.377.1.dist-info/RECORD +217 -0
  139. {bluer_objects-6.104.1.dist-info → bluer_objects-6.377.1.dist-info}/WHEEL +1 -1
  140. bluer_objects/.abcli/storage/download_file.sh +0 -9
  141. bluer_objects/.abcli/storage/exists.sh +0 -8
  142. bluer_objects/.abcli/storage/list.sh +0 -8
  143. bluer_objects/.abcli/storage/rm.sh +0 -11
  144. bluer_objects-6.104.1.dist-info/RECORD +0 -143
  145. {bluer_objects-6.104.1.dist-info → bluer_objects-6.377.1.dist-info}/licenses/LICENSE +0 -0
  146. {bluer_objects-6.104.1.dist-info → bluer_objects-6.377.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,26 @@
1
+ from bluer_options import string
2
+
3
+ from bluer_objects import objects
4
+ from bluer_objects.mlflow.lock.functions import lock, unlock
5
+
6
+
7
+ def test_mlflow_lock():
8
+ object_name = objects.unique_object("test_mlflow_lock")
9
+ lock_name = "lock-{}".format(string.random())
10
+
11
+ assert lock(
12
+ object_name=object_name,
13
+ lock_name=lock_name,
14
+ timeout=10,
15
+ )
16
+
17
+ assert not lock(
18
+ object_name=object_name,
19
+ lock_name=lock_name,
20
+ timeout=10,
21
+ )
22
+
23
+ assert unlock(
24
+ object_name=object_name,
25
+ lock_name=lock_name,
26
+ )
@@ -41,6 +41,7 @@ def test_objects_list_of_files(
41
41
 
42
42
  def test_object_object_path():
43
43
  object_name = objects.unique_object("test_object_object_path")
44
+
44
45
  object_path = objects.object_path(object_name, create=True)
45
46
  assert object_path
46
47
  assert path.exists(object_path)
@@ -61,5 +62,6 @@ def test_objects_path_of(test_object):
61
62
  )
62
63
  def test_objects_unique_object(prefix: str):
63
64
  object_name = objects.unique_object(prefix)
65
+
64
66
  assert object_name
65
67
  assert object_name.startswith(prefix)
@@ -0,0 +1,34 @@
1
+ import pytest
2
+
3
+ from bluer_objects.host.functions import shell
4
+
5
+
6
+ @pytest.mark.parametrize(
7
+ ["command"],
8
+ [
9
+ ["ls"],
10
+ ["ls *"],
11
+ [
12
+ [
13
+ "ls",
14
+ "*",
15
+ ],
16
+ ],
17
+ ],
18
+ )
19
+ def test_shell(command: str):
20
+ success = shell(
21
+ command=command,
22
+ log=True,
23
+ )
24
+ assert success
25
+
26
+ success, output = shell(
27
+ command=command,
28
+ return_output=True,
29
+ log=True,
30
+ )
31
+ assert success
32
+ assert isinstance(output, list)
33
+ for item in output:
34
+ assert isinstance(item, str)
@@ -1,34 +1,20 @@
1
- from bluer_options import string
2
-
3
- from bluer_objects import file, objects
1
+ from bluer_objects import objects
4
2
  from bluer_objects import storage
3
+ from bluer_objects.testing import create_test_asset
5
4
 
6
5
 
7
6
  def test_storage():
8
7
  object_name = objects.unique_object("test_storage")
9
8
 
10
- depth = 10
11
-
12
- for filename in [
13
- "this.yaml",
14
- "that.yaml",
15
- "subfolder/this.yaml",
16
- "subfolder/that.yaml",
17
- ]:
18
- assert file.save_yaml(
19
- objects.path_of(
20
- object_name=object_name,
21
- filename=filename,
22
- ),
23
- {
24
- string.random(length=depth): string.random(length=depth)
25
- for _ in range(depth)
26
- },
27
- )
9
+ assert create_test_asset(
10
+ object_name=object_name,
11
+ depth=10,
12
+ )
28
13
 
29
14
  for filename in [
30
15
  "this.yaml",
31
16
  "subfolder/this.yaml",
17
+ "test-00.png",
32
18
  ]:
33
19
  assert storage.upload(
34
20
  object_name=object_name,
@@ -40,6 +26,7 @@ def test_storage():
40
26
  for filename in [
41
27
  "this.yaml",
42
28
  "subfolder/this.yaml",
29
+ "test-00.png",
43
30
  ]:
44
31
  assert storage.download(
45
32
  object_name=object_name,
@@ -0,0 +1,39 @@
1
+ from bluer_objects import objects
2
+ from bluer_objects.testing import create_test_asset
3
+ from bluer_objects.storage import StorageInterface
4
+
5
+
6
+ def test_storage_base():
7
+ object_name = objects.unique_object("test_storage_base")
8
+
9
+ assert create_test_asset(
10
+ object_name=object_name,
11
+ depth=10,
12
+ )
13
+
14
+ storage = StorageInterface()
15
+
16
+ success, list_of_files_local = storage.ls(
17
+ object_name=object_name,
18
+ where="local",
19
+ )
20
+ assert success
21
+ assert list_of_files_local
22
+
23
+ success, list_of_files_cloud = storage.ls(
24
+ object_name=object_name,
25
+ where="cloud",
26
+ )
27
+ assert not success
28
+ assert not list_of_files_cloud
29
+
30
+ assert storage.upload(object_name=object_name)
31
+
32
+ success, list_of_files_cloud = storage.ls(
33
+ object_name=object_name,
34
+ where="cloud",
35
+ )
36
+ assert not success
37
+ assert not list_of_files_cloud
38
+
39
+ assert storage.download(object_name=object_name)
@@ -0,0 +1,67 @@
1
+ from bluer_objects import objects
2
+ from bluer_objects.testing import create_test_asset
3
+ from bluer_objects.storage import S3Interface
4
+
5
+
6
+ def test_storage_s3():
7
+ object_name = objects.unique_object("test_storage_s3")
8
+
9
+ assert create_test_asset(
10
+ object_name=object_name,
11
+ depth=10,
12
+ )
13
+
14
+ storage = S3Interface()
15
+
16
+ success, list_of_files_local = storage.ls(
17
+ object_name=object_name,
18
+ where="local",
19
+ )
20
+ assert success
21
+ assert list_of_files_local
22
+
23
+ success, list_of_files_cloud = storage.ls(
24
+ object_name=object_name,
25
+ where="cloud",
26
+ )
27
+ assert success
28
+ assert not list_of_files_cloud
29
+
30
+ for filename in [
31
+ "this.yaml",
32
+ "subfolder/this.yaml",
33
+ "test-00.png",
34
+ ]:
35
+ assert storage.upload(
36
+ object_name=object_name,
37
+ filename=filename,
38
+ )
39
+
40
+ success, list_of_files_cloud = storage.ls(
41
+ object_name=object_name,
42
+ where="cloud",
43
+ )
44
+ assert success
45
+ assert list_of_files_cloud
46
+
47
+ assert storage.upload(object_name=object_name)
48
+
49
+ success, list_of_files_cloud = storage.ls(
50
+ object_name=object_name,
51
+ where="cloud",
52
+ )
53
+ assert success
54
+ assert list_of_files_cloud
55
+ assert list_of_files_cloud == list_of_files_local
56
+
57
+ for filename in [
58
+ "this.yaml",
59
+ "subfolder/this.yaml",
60
+ "test-00.png",
61
+ ]:
62
+ assert storage.download(
63
+ object_name=object_name,
64
+ filename=filename,
65
+ )
66
+
67
+ assert storage.download(object_name=object_name)
@@ -0,0 +1,75 @@
1
+ import pytest
2
+
3
+ from bluer_objects import objects
4
+ from bluer_objects.testing import create_test_asset
5
+ from bluer_objects.storage import WebDAVRequestInterface
6
+
7
+
8
+ @pytest.mark.skip(reason="nodisk is super slow")
9
+ def test_storage_webdav_request():
10
+ object_name = objects.unique_object("test_storage_webdav_request")
11
+
12
+ assert create_test_asset(
13
+ object_name=object_name,
14
+ depth=10,
15
+ )
16
+
17
+ storage = WebDAVRequestInterface()
18
+
19
+ success, list_of_files_local = storage.ls(
20
+ object_name=object_name,
21
+ where="local",
22
+ )
23
+ assert success
24
+ assert list_of_files_local
25
+
26
+ success, list_of_files_cloud = storage.ls(
27
+ object_name=object_name,
28
+ where="cloud",
29
+ )
30
+ assert success
31
+ assert not list_of_files_cloud
32
+
33
+ for filename in [
34
+ "this.yaml",
35
+ "subfolder/this.yaml",
36
+ "test-00.png",
37
+ ]:
38
+ assert storage.upload(
39
+ object_name=object_name,
40
+ filename=filename,
41
+ )
42
+
43
+ success, list_of_files_cloud = storage.ls(
44
+ object_name=object_name,
45
+ where="cloud",
46
+ )
47
+ assert success
48
+ assert list_of_files_cloud
49
+
50
+ assert storage.upload(object_name=object_name)
51
+
52
+ success, list_of_files_cloud = storage.ls(
53
+ object_name=object_name,
54
+ where="cloud",
55
+ )
56
+ assert success
57
+ assert list_of_files_cloud
58
+ assert list_of_files_cloud == list_of_files_local
59
+
60
+ for filename in [
61
+ "this.yaml",
62
+ "subfolder/this.yaml",
63
+ "test-00.png",
64
+ ]:
65
+ assert storage.download(
66
+ object_name=object_name,
67
+ filename=filename,
68
+ )
69
+
70
+ assert storage.download(object_name=object_name)
71
+
72
+ assert storage.delete(
73
+ object_name=object_name,
74
+ do_dryrun=False,
75
+ )
@@ -0,0 +1,42 @@
1
+ import pytest
2
+
3
+ from bluer_objects import objects
4
+ from bluer_objects.testing import create_test_asset
5
+ from bluer_objects.storage import WebDAVzipInterface
6
+
7
+
8
+ @pytest.mark.skip(reason="nodisk is super slow")
9
+ def test_storage_webdav_zip():
10
+ object_name = objects.unique_object("test_storage_webdav_zip")
11
+
12
+ assert create_test_asset(
13
+ object_name=object_name,
14
+ depth=10,
15
+ )
16
+
17
+ storage = WebDAVzipInterface()
18
+
19
+ success, list_of_files_local = storage.ls(
20
+ object_name=object_name,
21
+ where="local",
22
+ )
23
+ assert success
24
+ assert list_of_files_local
25
+
26
+ success, list_of_files_cloud = storage.ls(
27
+ object_name=object_name,
28
+ where="cloud",
29
+ )
30
+ assert success
31
+ assert not list_of_files_cloud
32
+
33
+ assert storage.upload(object_name=object_name)
34
+
35
+ success, list_of_files_cloud = storage.ls(
36
+ object_name=object_name,
37
+ where="cloud",
38
+ )
39
+ assert success
40
+ assert list_of_files_cloud
41
+
42
+ assert storage.download(object_name=object_name)
@@ -0,0 +1,11 @@
1
+ from bluer_objects.web.functions import is_accessible
2
+ from bluer_ai.env import abcli_is_github_workflow
3
+
4
+
5
+ def test_url_is_accessible():
6
+ success = is_accessible("void")
7
+ assert not success
8
+
9
+ url = "https://cnn.com" if abcli_is_github_workflow else "https://iribnews.ir"
10
+ success = is_accessible(url)
11
+ assert success
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,31 @@
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.web.functions import is_accessible
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="is_accessible",
17
+ )
18
+ parser.add_argument(
19
+ "--url",
20
+ type=str,
21
+ )
22
+ args = parser.parse_args()
23
+
24
+ success = False
25
+ if args.task == "is_accessible":
26
+ success = True
27
+ print(int(is_accessible(args.url)))
28
+ else:
29
+ success = None
30
+
31
+ sys_exit(logger, NAME, args.task, success)
@@ -0,0 +1,9 @@
1
+ import requests
2
+
3
+
4
+ def is_accessible(url) -> bool:
5
+ try:
6
+ response = requests.get(url)
7
+ return response.status_code == 200
8
+ except:
9
+ return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bluer_objects
3
- Version: 6.104.1
3
+ Version: 6.377.1
4
4
  Summary: 🌀 Object management in Bash.
5
5
  Home-page: https://github.com/kamangir/bluer-objects
6
6
  Author: Arash Abadpour (Kamangir)
@@ -12,6 +12,7 @@ Classifier: Operating System :: OS Independent
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
14
  Requires-Dist: bluer_ai
15
+ Requires-Dist: boto3
15
16
  Requires-Dist: webdavclient3
16
17
  Requires-Dist: dill
17
18
  Requires-Dist: mlflow
@@ -35,7 +36,7 @@ Dynamic: summary
35
36
 
36
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/). Examples are 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).
37
38
 
38
- Also home to 🌀 [bluer README](https://github.com/kamangir/bluer-objects/blob/main/bluer_objects/README/).
39
+ Also home to 🌀 [bluer README](https://github.com/kamangir/bluer-objects/blob/main/bluer_objects/README/), and the 🔒 [`Lock`](https://github.com/kamangir/bluer-objects/blob/main/bluer_objects/mlflow/lock/).
39
40
 
40
41
  # installation
41
42
 
@@ -45,6 +46,7 @@ pip install bluer-objects
45
46
 
46
47
  # aliases
47
48
 
49
+ [@assets](https://github.com/kamangir/bluer-objects/blob/main/bluer_objects/docs/aliases/assets.md),
48
50
  [@clone](https://github.com/kamangir/bluer-objects/blob/main/bluer_objects/docs/aliases/clone.md),
49
51
  [@download](https://github.com/kamangir/bluer-objects/blob/main/bluer_objects/docs/aliases/download.md),
50
52
  [@gif](https://github.com/kamangir/bluer-objects/blob/main/bluer_objects/docs/aliases/gif.md),
@@ -52,6 +54,7 @@ pip install bluer-objects
52
54
  [@ls](https://github.com/kamangir/bluer-objects/blob/main/bluer_objects/docs/aliases/ls.md),
53
55
  [@metadata](https://github.com/kamangir/bluer-objects/blob/main/bluer_objects/docs/aliases/metadata.md),
54
56
  [@mlflow](https://github.com/kamangir/bluer-objects/blob/main/bluer_objects/docs/aliases/mlflow.md),
57
+ [@pdf](https://github.com/kamangir/bluer-objects/blob/main/bluer_objects/docs/aliases/pdf.md),
55
58
  [@upload](https://github.com/kamangir/bluer-objects/blob/main/bluer_objects/docs/aliases/upload.md).
56
59
 
57
60
  ---
@@ -63,6 +66,6 @@ pip install bluer-objects
63
66
 
64
67
  [![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)
65
68
 
66
- built by 🌀 [`bluer README`](https://github.com/kamangir/bluer-objects/tree/main/bluer_objects/README), based on 🌀 [`bluer_objects-6.104.1`](https://github.com/kamangir/bluer-objects).
69
+ built by 🌀 [`bluer README`](https://github.com/kamangir/bluer-objects/tree/main/bluer_objects/README), based on 🌀 [`bluer_objects-6.377.1`](https://github.com/kamangir/bluer-objects).
67
70
 
68
71
  built by 🌀 [`blueness-3.118.1`](https://github.com/kamangir/blueness).