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
@@ -3,6 +3,7 @@ from typing import List
3
3
  from bluer_options.terminal import show_usage, xtra
4
4
 
5
5
  from bluer_objects.help.mlflow.cache import help_functions as help_cache
6
+ from bluer_objects.help.mlflow.lock import help_functions as help_lock
6
7
  from bluer_objects.help.mlflow.tags import help_functions as help_tags
7
8
  from bluer_ai import env
8
9
 
@@ -29,7 +30,7 @@ def help_deploy(
29
30
  tokens: List[str],
30
31
  mono: bool,
31
32
  ) -> str:
32
- options = xtra("dryrun,~local,port=<5001>", mono=mono)
33
+ options = xtra("dryrun,port=<5001>", mono=mono)
33
34
 
34
35
  return show_usage(
35
36
  [
@@ -42,6 +43,22 @@ def help_deploy(
42
43
  )
43
44
 
44
45
 
46
+ def help_deploy_set(
47
+ tokens: List[str],
48
+ mono: bool,
49
+ ) -> str:
50
+ return show_usage(
51
+ [
52
+ "@mlflow",
53
+ "deploy",
54
+ "set",
55
+ "<url> | local",
56
+ ],
57
+ "set mlflow deployment.",
58
+ mono=mono,
59
+ )
60
+
61
+
45
62
  def help_get_id(
46
63
  tokens: List[str],
47
64
  mono: bool,
@@ -198,10 +215,14 @@ def help_transition(
198
215
  help_functions = {
199
216
  "browse": help_browse,
200
217
  "cache": help_cache,
201
- "deploy": help_deploy,
218
+ "deploy": {
219
+ "": help_deploy,
220
+ "set": help_deploy_set,
221
+ },
202
222
  "get_id": help_get_id,
203
223
  "get_run_id": help_get_run_id,
204
224
  "list_registered_models": help_list_registered_models,
225
+ "lock": help_lock,
205
226
  "log_artifacts": help_log_artifacts,
206
227
  "log_run": help_log_run,
207
228
  "rm": help_rm,
@@ -0,0 +1,52 @@
1
+ from typing import List
2
+
3
+ from bluer_options.terminal import show_usage, xtra
4
+
5
+
6
+ def help_lock(
7
+ tokens: List[str],
8
+ mono: bool,
9
+ ) -> str:
10
+ args = [
11
+ "[--lock <lock-name>]",
12
+ "[--timeout <10>]",
13
+ "[--verbose 0]",
14
+ ]
15
+
16
+ return show_usage(
17
+ [
18
+ "@lock",
19
+ "lock",
20
+ "[.|<object-name>]",
21
+ ]
22
+ + args,
23
+ "lock <object-name>.",
24
+ mono=mono,
25
+ )
26
+
27
+
28
+ def help_unlock(
29
+ tokens: List[str],
30
+ mono: bool,
31
+ ) -> str:
32
+ args = [
33
+ "[--lock <lock-name>]",
34
+ "[--verbose 0]",
35
+ ]
36
+
37
+ return show_usage(
38
+ [
39
+ "@lock",
40
+ "unlock",
41
+ "[.|<object-name>]",
42
+ ]
43
+ + args,
44
+ "unlock <object-name>.",
45
+ mono=mono,
46
+ )
47
+
48
+
49
+ help_functions = {
50
+ "lock": help_lock,
51
+ "unlock": help_unlock,
52
+ }
@@ -0,0 +1,67 @@
1
+ from typing import List
2
+
3
+ from bluer_options.terminal import show_usage, xtra
4
+
5
+
6
+ def help_convert(
7
+ tokens: List[str],
8
+ mono: bool,
9
+ ) -> str:
10
+ options = "".join(
11
+ [
12
+ "combine",
13
+ xtra(",~compress,filename=<release.pdf>,install,", mono=mono),
14
+ "upload",
15
+ ]
16
+ )
17
+
18
+ args = [
19
+ "[--count <2>]",
20
+ ]
21
+
22
+ # ---
23
+
24
+ usage_1 = show_usage(
25
+ [
26
+ "@pdf",
27
+ "convert",
28
+ "[{}]".format(f"inline,{options}"),
29
+ "<module-name>",
30
+ "<.,this,this/that.md,this/that.jpg,this/that.pdf>",
31
+ "[-|<object-name>]",
32
+ ]
33
+ + args,
34
+ "md -> pdf.",
35
+ mono=mono,
36
+ )
37
+
38
+ # ---
39
+
40
+ usage_2 = show_usage(
41
+ [
42
+ "@pdf",
43
+ "convert",
44
+ f"[{options}]",
45
+ "[.|<object-name>]",
46
+ ]
47
+ + args
48
+ + [
49
+ "[--list_missing 0]",
50
+ ],
51
+ "md -> pdf.",
52
+ mono=mono,
53
+ )
54
+
55
+ # ---
56
+
57
+ return "\n".join(
58
+ [
59
+ usage_1,
60
+ usage_2,
61
+ ]
62
+ )
63
+
64
+
65
+ help_functions = {
66
+ "convert": help_convert,
67
+ }
@@ -3,16 +3,23 @@ from typing import List
3
3
  from bluer_options.terminal import show_usage, xtra
4
4
 
5
5
 
6
+ def options(mono: bool) -> str:
7
+ return "".join(
8
+ [
9
+ "filename=<filename>",
10
+ xtra(",public,zip", mono=mono),
11
+ ]
12
+ )
13
+
14
+
6
15
  def help_upload(
7
16
  tokens: List[str],
8
17
  mono: bool,
9
18
  ) -> str:
10
- options = "filename=<filename>"
11
-
12
19
  return show_usage(
13
20
  [
14
21
  "@upload",
15
- f"[{options}]",
22
+ f"[{options(mono=mono)}]",
16
23
  "[.|<object-name>]",
17
24
  ],
18
25
  "upload <object-name>.",
@@ -0,0 +1,38 @@
1
+ from typing import List
2
+
3
+ from bluer_options.terminal import show_usage
4
+
5
+
6
+ def help_is_accessible(
7
+ tokens: List[str],
8
+ mono: bool,
9
+ ) -> str:
10
+ return show_usage(
11
+ [
12
+ "@web",
13
+ "is_accessible",
14
+ "<url>",
15
+ ],
16
+ "is <url> accessible?",
17
+ mono=mono,
18
+ )
19
+
20
+
21
+ def help_where_am_i(
22
+ tokens: List[str],
23
+ mono: bool,
24
+ ) -> str:
25
+ return show_usage(
26
+ [
27
+ "@web",
28
+ "where_am_i",
29
+ ],
30
+ "where am I?",
31
+ mono=mono,
32
+ )
33
+
34
+
35
+ help_functions = {
36
+ "is_accessible": help_is_accessible,
37
+ "where_am_i": help_where_am_i,
38
+ }
@@ -11,7 +11,7 @@ NAME = module.name(__file__, NAME)
11
11
 
12
12
 
13
13
  def shell(
14
- command: str,
14
+ command: Union[str, List[str]],
15
15
  clean_after: bool = False,
16
16
  return_output: bool = False,
17
17
  work_dir: str = ".",
@@ -20,6 +20,9 @@ def shell(
20
20
  bool,
21
21
  Tuple[bool, List[str]],
22
22
  ]:
23
+ if isinstance(command, list):
24
+ command = " ".join(command)
25
+
23
26
  if log:
24
27
  logger.info(f"{NAME}.shell({command})")
25
28
 
@@ -0,0 +1,76 @@
1
+ import matplotlib.pyplot as plt
2
+ import numpy as np
3
+ from typing import List
4
+
5
+ from bluer_objects.graphics.signature import justify_text
6
+ from bluer_objects import file
7
+
8
+
9
+ def log_confusion_matrix(
10
+ confusion_matrix: np.ndarray,
11
+ filename: str,
12
+ header: List[str] = [],
13
+ footer: List[str] = [],
14
+ x_classes: List[str] = [],
15
+ y_classes: List[str] = [],
16
+ x_name: str = "prediction",
17
+ y_name: str = "label",
18
+ line_width: int = 80,
19
+ log: bool = True,
20
+ figsize: tuple = (10, 10),
21
+ ) -> bool:
22
+ fig, ax = plt.subplots(figsize=figsize)
23
+ cax = ax.imshow(
24
+ confusion_matrix,
25
+ interpolation="nearest",
26
+ cmap=plt.cm.Blues,
27
+ )
28
+ fig.colorbar(cax)
29
+ ax.set_title(
30
+ justify_text(
31
+ " | ".join(header),
32
+ line_width=line_width,
33
+ return_str=True,
34
+ )
35
+ )
36
+ ax.set_xlabel(
37
+ justify_text(
38
+ " | ".join([x_name] + footer),
39
+ line_width=line_width,
40
+ return_str=True,
41
+ )
42
+ )
43
+ ax.set_ylabel(y_name)
44
+
45
+ if not x_classes:
46
+ x_classes = [f"class #{index}" for index in range(confusion_matrix.shape[1])]
47
+ if not y_classes:
48
+ y_classes = [f"class #{index}" for index in range(confusion_matrix.shape[0])]
49
+
50
+ ax.set_xticks(np.arange(confusion_matrix.shape[1]))
51
+ ax.set_yticks(np.arange(confusion_matrix.shape[0]))
52
+ ax.set_xticklabels(
53
+ x_classes,
54
+ rotation=45,
55
+ ha="right",
56
+ )
57
+ ax.set_yticklabels(y_classes)
58
+
59
+ threshold = confusion_matrix.max() / 2.0
60
+ for i in range(confusion_matrix.shape[0]):
61
+ for j in range(confusion_matrix.shape[1]):
62
+ ax.text(
63
+ j,
64
+ i,
65
+ f"{100*confusion_matrix[i, j]:.1f}%",
66
+ ha="center",
67
+ va="center",
68
+ color="white" if confusion_matrix[i, j] > threshold else "black",
69
+ )
70
+
71
+ plt.tight_layout()
72
+
73
+ return file.save_fig(
74
+ filename,
75
+ log=log,
76
+ )
@@ -0,0 +1,110 @@
1
+ import matplotlib.pyplot as plt
2
+ from typing import Dict, Any, Union, List
3
+ import pandas as pd
4
+ import random
5
+ import os
6
+
7
+ from bluer_options import string
8
+
9
+ from bluer_objects import file, objects, path
10
+ from bluer_objects.graphics.signature import sign_filename
11
+
12
+ LOG_IMAGE_GRID_COLS = 5
13
+ LOG_IMAGE_GRID_ROWS = 3
14
+
15
+
16
+ def log_image_grid(
17
+ items: Union[
18
+ List[Dict[str, Any]],
19
+ pd.DataFrame,
20
+ ],
21
+ filename: str,
22
+ rows: int = LOG_IMAGE_GRID_ROWS,
23
+ cols: int = LOG_IMAGE_GRID_COLS,
24
+ log: bool = True,
25
+ verbose: bool = False,
26
+ scale: int = 2,
27
+ shuffle: bool = False,
28
+ header: List[str] = [],
29
+ footer: List[str] = [],
30
+ relative_path: bool = False,
31
+ ) -> bool:
32
+ if isinstance(items, pd.DataFrame):
33
+ items = items.to_dict("records")
34
+
35
+ while len(items) < rows * cols:
36
+ items += [{"pass": True}]
37
+ if shuffle:
38
+ random.shuffle(items)
39
+
40
+ items = items[: rows * cols]
41
+
42
+ if relative_path:
43
+ root_path = file.path(filename)
44
+ for item in items:
45
+ if item.get("filename", ""):
46
+ item["filename"] = os.path.join(
47
+ root_path,
48
+ item["filename"],
49
+ )
50
+
51
+ _, axes = plt.subplots(
52
+ rows,
53
+ cols,
54
+ figsize=(
55
+ scale * cols,
56
+ scale * rows,
57
+ ),
58
+ )
59
+ axes = axes.flatten()
60
+
61
+ image_shape = ""
62
+ for i, item in enumerate(items):
63
+ if item.get("pass", False):
64
+ axes[i].axis("off")
65
+ continue
66
+
67
+ if item.get("filename", ""):
68
+ success, item["image"] = file.load_image(
69
+ item.get("filename", ""),
70
+ log=verbose,
71
+ )
72
+ if not success:
73
+ return False
74
+
75
+ ax = axes[i]
76
+ image = item["image"]
77
+ image_shape = string.pretty_shape_of_matrix(image)
78
+ ax.imshow(
79
+ image,
80
+ cmap="gray" if image.ndim == 2 else None,
81
+ )
82
+ ax.set_title(
83
+ item.get("title", f"#{i}"),
84
+ color=item.get("color", "black"),
85
+ fontsize=10,
86
+ )
87
+ ax.axis("off")
88
+
89
+ plt.tight_layout()
90
+
91
+ if not file.save_fig(
92
+ filename,
93
+ log=verbose,
94
+ ):
95
+ return False
96
+
97
+ return sign_filename(
98
+ filename,
99
+ [
100
+ " | ".join(
101
+ objects.signature(
102
+ info=file.name_and_extension(filename),
103
+ object_name=path.name(file.path(filename)),
104
+ )
105
+ + [image_shape]
106
+ + header
107
+ )
108
+ ],
109
+ [" | ".join(footer)],
110
+ )
@@ -0,0 +1,107 @@
1
+ from typing import List
2
+ import numpy as np
3
+
4
+ from blueness import module
5
+ from bluer_options import string
6
+
7
+ from bluer_objects import NAME
8
+ from bluer_objects.logger import logger
9
+
10
+ NAME = module.name(__file__, NAME)
11
+
12
+
13
+ def stitch_images(
14
+ list_of_images: List[np.ndarray],
15
+ cols: int = -1,
16
+ rows: int = -1,
17
+ log: bool = False,
18
+ ) -> np.ndarray:
19
+ if not list_of_images:
20
+ return np.zeros((1, 1, 3), dtype=np.uint8)
21
+
22
+ list_of_images = list_of_images.copy()
23
+
24
+ if rows == -1:
25
+ rows = int(np.floor(np.sqrt(len(list_of_images))))
26
+ cols = -1
27
+
28
+ if cols == -1:
29
+ cols = int(np.ceil(len(list_of_images) / rows))
30
+
31
+ if log:
32
+ logger.info(
33
+ "{}.stitch_images[{}x{}]({}): {}".format(
34
+ NAME,
35
+ rows,
36
+ cols,
37
+ len(list_of_images),
38
+ ", ".join(
39
+ [string.pretty_shape_of_matrix(image) for image in list_of_images]
40
+ ),
41
+ )
42
+ )
43
+
44
+ for image in list_of_images:
45
+ if len(image.shape) == 2:
46
+ image = np.stack([image, image, image], axis=2)
47
+
48
+ if rows == 1:
49
+ output = np.zeros(
50
+ (
51
+ max([image.shape[0] for image in list_of_images]),
52
+ sum([image.shape[1] for image in list_of_images]),
53
+ 3,
54
+ ),
55
+ dtype=np.uint8,
56
+ )
57
+ x: int = 0
58
+ for image in list_of_images:
59
+ x_new = x + image.shape[1]
60
+
61
+ output[
62
+ : image.shape[0],
63
+ x:x_new,
64
+ :,
65
+ ] = image
66
+
67
+ x = x_new
68
+
69
+ return output
70
+
71
+ if cols == 1:
72
+ output = np.zeros(
73
+ (
74
+ sum([image.shape[0] for image in list_of_images]),
75
+ max([image.shape[1] for image in list_of_images]),
76
+ 3,
77
+ ),
78
+ dtype=np.uint8,
79
+ )
80
+ y: int = 0
81
+ for image in list_of_images:
82
+ y_new = y + image.shape[0]
83
+
84
+ output[
85
+ y:y_new,
86
+ : image.shape[1],
87
+ :,
88
+ ] = image
89
+
90
+ y = y_new
91
+
92
+ return output
93
+
94
+ return stitch_images(
95
+ list_of_images=[
96
+ stitch_images(
97
+ list_of_images[row * cols : (row + 1) * cols],
98
+ cols=cols,
99
+ rows=1,
100
+ log=log,
101
+ )
102
+ for row in range(rows)
103
+ ],
104
+ cols=1,
105
+ rows=rows,
106
+ log=log,
107
+ )
bluer_objects/markdown.py CHANGED
@@ -12,6 +12,7 @@ NAME = module.name(__file__, NAME)
12
12
  def generate_table(
13
13
  items: List[str],
14
14
  cols: int = 3,
15
+ log: bool = True,
15
16
  ) -> List[str]:
16
17
  if not items:
17
18
  return []
@@ -22,13 +23,14 @@ def generate_table(
22
23
 
23
24
  row_count = int(math.ceil(len(items) / cols))
24
25
 
25
- logger.info(
26
- "{}.generate_table(): {} item(s), {} row(s)".format(
27
- NAME,
28
- len(items),
29
- row_count,
26
+ if log:
27
+ logger.info(
28
+ "{}.generate_table(): {} item(s), {} row(s)".format(
29
+ NAME,
30
+ len(items),
31
+ row_count,
32
+ )
30
33
  )
31
- )
32
34
 
33
35
  return [
34
36
  "| {} |".format(" | ".join(cols * [" "])),
@@ -5,4 +5,5 @@ from bluer_objects.metadata.get import (
5
5
  get_from_object,
6
6
  get_from_path,
7
7
  )
8
+ from bluer_objects.metadata.flatten import flatten
8
9
  from bluer_objects.metadata.post import post, post_to_file, post_to_object, post_to_path
@@ -0,0 +1,27 @@
1
+ from typing import Any
2
+ import numpy as np
3
+
4
+
5
+ def flatten(obj: Any) -> Any:
6
+ if isinstance(obj, dict):
7
+ return {k: flatten(v) for k, v in obj.items()}
8
+
9
+ if isinstance(obj, list):
10
+ return [flatten(x) for x in obj]
11
+
12
+ if isinstance(obj, tuple):
13
+ return tuple(flatten(x) for x in obj)
14
+
15
+ if isinstance(obj, np.ndarray):
16
+ return obj.tolist()
17
+
18
+ if hasattr(obj, "__dict__"):
19
+ return flatten(vars(obj))
20
+
21
+ if isinstance(obj, (int, float, str)):
22
+ return obj
23
+
24
+ try:
25
+ return str(obj)
26
+ except:
27
+ return obj.__class__.__name__
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,58 @@
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.mlflow.lock.functions import lock, unlock
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="lock | unlock",
17
+ )
18
+ parser.add_argument(
19
+ "--object_name",
20
+ type=str,
21
+ )
22
+ parser.add_argument(
23
+ "--lock",
24
+ type=str,
25
+ default="lock",
26
+ )
27
+ parser.add_argument(
28
+ "--timeout",
29
+ type=int,
30
+ default=-1,
31
+ help="in seconds",
32
+ )
33
+ parser.add_argument(
34
+ "--verbose",
35
+ type=int,
36
+ default=1,
37
+ help="0 | 1",
38
+ )
39
+ args = parser.parse_args()
40
+
41
+ success = False
42
+ if args.task == "lock":
43
+ success = lock(
44
+ object_name=args.object_name,
45
+ lock_name=args.lock,
46
+ timeout=args.timeout,
47
+ verbose=args.verbose == 1,
48
+ )
49
+ elif args.task == "unlock":
50
+ success = unlock(
51
+ object_name=args.object_name,
52
+ lock_name=args.lock,
53
+ verbose=args.verbose == 1,
54
+ )
55
+ else:
56
+ success = None
57
+
58
+ sys_exit(logger, NAME, args.task, success)