bluer-objects 6.3.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.
- bluer_objects/.abcli/abcli.sh +9 -0
- bluer_objects/.abcli/actions.sh +11 -0
- bluer_objects/.abcli/aka.sh +3 -0
- bluer_objects/.abcli/alias.sh +36 -0
- bluer_objects/.abcli/blue_objects.sh +11 -0
- bluer_objects/.abcli/cache.sh +5 -0
- bluer_objects/.abcli/clone.sh +94 -0
- bluer_objects/.abcli/download.sh +53 -0
- bluer_objects/.abcli/file.sh +8 -0
- bluer_objects/.abcli/gif.sh +27 -0
- bluer_objects/.abcli/host.sh +29 -0
- bluer_objects/.abcli/ls.sh +24 -0
- bluer_objects/.abcli/metadata/get.sh +24 -0
- bluer_objects/.abcli/metadata/post.sh +22 -0
- bluer_objects/.abcli/metadata.sh +16 -0
- bluer_objects/.abcli/mlflow/browse.sh +36 -0
- bluer_objects/.abcli/mlflow/cache.sh +31 -0
- bluer_objects/.abcli/mlflow/list_registered_models.sh +9 -0
- bluer_objects/.abcli/mlflow/log_artifacts.sh +10 -0
- bluer_objects/.abcli/mlflow/log_run.sh +10 -0
- bluer_objects/.abcli/mlflow/run.sh +11 -0
- bluer_objects/.abcli/mlflow/tags/clone.sh +15 -0
- bluer_objects/.abcli/mlflow/tags/get.sh +10 -0
- bluer_objects/.abcli/mlflow/tags/search.sh +12 -0
- bluer_objects/.abcli/mlflow/tags/set.sh +13 -0
- bluer_objects/.abcli/mlflow/tags.sh +16 -0
- bluer_objects/.abcli/mlflow/test.sh +11 -0
- bluer_objects/.abcli/mlflow/transition.sh +20 -0
- bluer_objects/.abcli/mlflow.sh +29 -0
- bluer_objects/.abcli/mysql/cache.sh +65 -0
- bluer_objects/.abcli/mysql/relations.sh +83 -0
- bluer_objects/.abcli/mysql/tags.sh +85 -0
- bluer_objects/.abcli/mysql.sh +16 -0
- bluer_objects/.abcli/object.sh +54 -0
- bluer_objects/.abcli/publish.sh +58 -0
- bluer_objects/.abcli/select.sh +34 -0
- bluer_objects/.abcli/storage/clear.sh +45 -0
- bluer_objects/.abcli/storage/download_file.sh +9 -0
- bluer_objects/.abcli/storage/exists.sh +8 -0
- bluer_objects/.abcli/storage/list.sh +8 -0
- bluer_objects/.abcli/storage/rm.sh +11 -0
- bluer_objects/.abcli/storage/status.sh +11 -0
- bluer_objects/.abcli/storage.sh +15 -0
- bluer_objects/.abcli/tags.sh +5 -0
- bluer_objects/.abcli/tests/README.sh +8 -0
- bluer_objects/.abcli/tests/clone.sh +32 -0
- bluer_objects/.abcli/tests/help.sh +85 -0
- bluer_objects/.abcli/tests/host.sh +7 -0
- bluer_objects/.abcli/tests/ls.sh +13 -0
- bluer_objects/.abcli/tests/metadata.sh +53 -0
- bluer_objects/.abcli/tests/mlflow_cache.sh +14 -0
- bluer_objects/.abcli/tests/mlflow_logging.sh +12 -0
- bluer_objects/.abcli/tests/mlflow_tags.sh +29 -0
- bluer_objects/.abcli/tests/mlflow_test.sh +7 -0
- bluer_objects/.abcli/tests/mysql_cache.sh +15 -0
- bluer_objects/.abcli/tests/mysql_relations.sh +20 -0
- bluer_objects/.abcli/tests/mysql_tags.sh +16 -0
- bluer_objects/.abcli/tests/test_gif.sh +13 -0
- bluer_objects/.abcli/tests/version.sh +10 -0
- bluer_objects/.abcli/upload.sh +73 -0
- bluer_objects/README/__init__.py +29 -0
- bluer_objects/README/functions.py +285 -0
- bluer_objects/README/items.py +30 -0
- bluer_objects/__init__.py +19 -0
- bluer_objects/__main__.py +16 -0
- bluer_objects/config.env +22 -0
- bluer_objects/env.py +72 -0
- bluer_objects/file/__init__.py +41 -0
- bluer_objects/file/__main__.py +51 -0
- bluer_objects/file/classes.py +38 -0
- bluer_objects/file/functions.py +290 -0
- bluer_objects/file/load.py +219 -0
- bluer_objects/file/save.py +280 -0
- bluer_objects/graphics/__init__.py +4 -0
- bluer_objects/graphics/__main__.py +84 -0
- bluer_objects/graphics/frame.py +15 -0
- bluer_objects/graphics/gif.py +86 -0
- bluer_objects/graphics/screen.py +63 -0
- bluer_objects/graphics/signature.py +97 -0
- bluer_objects/graphics/text.py +165 -0
- bluer_objects/help/__init__.py +0 -0
- bluer_objects/help/__main__.py +10 -0
- bluer_objects/help/functions.py +5 -0
- bluer_objects/host/__init__.py +1 -0
- bluer_objects/host/__main__.py +84 -0
- bluer_objects/host/functions.py +66 -0
- bluer_objects/logger/__init__.py +4 -0
- bluer_objects/logger/matrix.py +209 -0
- bluer_objects/markdown.py +43 -0
- bluer_objects/metadata/__init__.py +8 -0
- bluer_objects/metadata/__main__.py +110 -0
- bluer_objects/metadata/enums.py +29 -0
- bluer_objects/metadata/get.py +89 -0
- bluer_objects/metadata/post.py +101 -0
- bluer_objects/mlflow/__init__.py +28 -0
- bluer_objects/mlflow/__main__.py +271 -0
- bluer_objects/mlflow/cache.py +13 -0
- bluer_objects/mlflow/logging.py +81 -0
- bluer_objects/mlflow/models.py +57 -0
- bluer_objects/mlflow/objects.py +76 -0
- bluer_objects/mlflow/runs.py +100 -0
- bluer_objects/mlflow/tags.py +90 -0
- bluer_objects/mlflow/testing.py +39 -0
- bluer_objects/mysql/cache/__init__.py +8 -0
- bluer_objects/mysql/cache/__main__.py +91 -0
- bluer_objects/mysql/cache/functions.py +181 -0
- bluer_objects/mysql/relations/__init__.py +9 -0
- bluer_objects/mysql/relations/__main__.py +138 -0
- bluer_objects/mysql/relations/functions.py +180 -0
- bluer_objects/mysql/table.py +144 -0
- bluer_objects/mysql/tags/__init__.py +1 -0
- bluer_objects/mysql/tags/__main__.py +130 -0
- bluer_objects/mysql/tags/functions.py +203 -0
- bluer_objects/objects.py +167 -0
- bluer_objects/path.py +194 -0
- bluer_objects/sample.env +16 -0
- bluer_objects/storage/__init__.py +3 -0
- bluer_objects/storage/__main__.py +114 -0
- bluer_objects/storage/classes.py +237 -0
- bluer_objects/tests/__init__.py +0 -0
- bluer_objects/tests/test_README.py +5 -0
- bluer_objects/tests/test_env.py +27 -0
- bluer_objects/tests/test_file_load_save.py +105 -0
- bluer_objects/tests/test_fullname.py +5 -0
- bluer_objects/tests/test_graphics.py +28 -0
- bluer_objects/tests/test_graphics_frame.py +11 -0
- bluer_objects/tests/test_graphics_gif.py +29 -0
- bluer_objects/tests/test_graphics_screen.py +8 -0
- bluer_objects/tests/test_graphics_signature.py +80 -0
- bluer_objects/tests/test_graphics_text.py +14 -0
- bluer_objects/tests/test_logger.py +5 -0
- bluer_objects/tests/test_logger_matrix.py +73 -0
- bluer_objects/tests/test_markdown.py +10 -0
- bluer_objects/tests/test_metadata.py +204 -0
- bluer_objects/tests/test_mlflow.py +60 -0
- bluer_objects/tests/test_mysql_cache.py +14 -0
- bluer_objects/tests/test_mysql_relations.py +16 -0
- bluer_objects/tests/test_mysql_table.py +9 -0
- bluer_objects/tests/test_mysql_tags.py +13 -0
- bluer_objects/tests/test_objects.py +180 -0
- bluer_objects/tests/test_path.py +7 -0
- bluer_objects/tests/test_storage.py +7 -0
- bluer_objects/tests/test_version.py +5 -0
- bluer_objects/urls.py +3 -0
- bluer_objects-6.3.1.dist-info/METADATA +57 -0
- bluer_objects-6.3.1.dist-info/RECORD +149 -0
- bluer_objects-6.3.1.dist-info/WHEEL +5 -0
- bluer_objects-6.3.1.dist-info/licenses/LICENSE +121 -0
- bluer_objects-6.3.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,114 @@
|
|
|
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.env import ABCLI_AWS_S3_BUCKET_NAME
|
|
8
|
+
from bluer_objects.storage.classes import Storage
|
|
9
|
+
from bluer_objects.logger import logger
|
|
10
|
+
|
|
11
|
+
NAME = module.name(__file__, NAME)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
parser = argparse.ArgumentParser(NAME)
|
|
15
|
+
parser.add_argument(
|
|
16
|
+
"task",
|
|
17
|
+
type=str,
|
|
18
|
+
default="",
|
|
19
|
+
help="create_bucket|download_file|exists|list_of_objects|upload_file",
|
|
20
|
+
)
|
|
21
|
+
parser.add_argument(
|
|
22
|
+
"--filename",
|
|
23
|
+
type=str,
|
|
24
|
+
default="",
|
|
25
|
+
)
|
|
26
|
+
parser.add_argument(
|
|
27
|
+
"--bucket_name",
|
|
28
|
+
type=str,
|
|
29
|
+
default=ABCLI_AWS_S3_BUCKET_NAME,
|
|
30
|
+
)
|
|
31
|
+
parser.add_argument(
|
|
32
|
+
"--count",
|
|
33
|
+
type=int,
|
|
34
|
+
default=9999,
|
|
35
|
+
)
|
|
36
|
+
parser.add_argument(
|
|
37
|
+
"--delim",
|
|
38
|
+
type=str,
|
|
39
|
+
default=", ",
|
|
40
|
+
)
|
|
41
|
+
parser.add_argument(
|
|
42
|
+
"--item_name",
|
|
43
|
+
default="object",
|
|
44
|
+
type=str,
|
|
45
|
+
)
|
|
46
|
+
parser.add_argument(
|
|
47
|
+
"--log",
|
|
48
|
+
default=1,
|
|
49
|
+
type=int,
|
|
50
|
+
help="0|1",
|
|
51
|
+
)
|
|
52
|
+
parser.add_argument(
|
|
53
|
+
"--object_name",
|
|
54
|
+
type=str,
|
|
55
|
+
default="",
|
|
56
|
+
)
|
|
57
|
+
parser.add_argument(
|
|
58
|
+
"--prefix",
|
|
59
|
+
type=str,
|
|
60
|
+
default="",
|
|
61
|
+
)
|
|
62
|
+
parser.add_argument(
|
|
63
|
+
"--recursive",
|
|
64
|
+
type=int,
|
|
65
|
+
default=1,
|
|
66
|
+
help="0|1",
|
|
67
|
+
)
|
|
68
|
+
parser.add_argument(
|
|
69
|
+
"--suffix",
|
|
70
|
+
type=str,
|
|
71
|
+
default="",
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
args = parser.parse_args()
|
|
75
|
+
|
|
76
|
+
delim = " " if args.delim == "space" else args.delim
|
|
77
|
+
|
|
78
|
+
success = True
|
|
79
|
+
output = None
|
|
80
|
+
if args.task == "create_bucket":
|
|
81
|
+
success = Storage(args.bucket_name).s3 is not None
|
|
82
|
+
elif args.task == "download_file":
|
|
83
|
+
success = Storage(args.bucket_name).download_file(
|
|
84
|
+
bucket_name=args.bucket_name,
|
|
85
|
+
object_name=args.object_name,
|
|
86
|
+
filename=args.filename,
|
|
87
|
+
)
|
|
88
|
+
elif args.task == "exists":
|
|
89
|
+
print(Storage(args.bucket_name).exists(args.object_name))
|
|
90
|
+
success = True
|
|
91
|
+
elif args.task == "list_of_objects":
|
|
92
|
+
output = Storage(args.bucket_name).list_of_objects(
|
|
93
|
+
count=args.count,
|
|
94
|
+
suffix=args.suffix,
|
|
95
|
+
prefix=args.prefix,
|
|
96
|
+
recursive=args.recursive,
|
|
97
|
+
)
|
|
98
|
+
success = True
|
|
99
|
+
elif args.task == "upload_file":
|
|
100
|
+
success = Storage(args.bucket_name).upload_file(
|
|
101
|
+
filename=args.filename,
|
|
102
|
+
object_name=args.object_name,
|
|
103
|
+
bucket_name=args.bucket_name,
|
|
104
|
+
)
|
|
105
|
+
else:
|
|
106
|
+
print(f"{NAME}: {args.task}: command not found.")
|
|
107
|
+
|
|
108
|
+
if success and output is not None:
|
|
109
|
+
if args.log:
|
|
110
|
+
print(f"{len(output):,} {args.item_name}(s): {delim.join(output)}")
|
|
111
|
+
else:
|
|
112
|
+
print(delim.join(output))
|
|
113
|
+
|
|
114
|
+
sys_exit(logger, NAME, args.task, success, log=args.log)
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
from typing import Union, Tuple
|
|
2
|
+
import boto3
|
|
3
|
+
import botocore
|
|
4
|
+
import os
|
|
5
|
+
import os.path
|
|
6
|
+
import time
|
|
7
|
+
|
|
8
|
+
from blueness import module
|
|
9
|
+
from blue_options import string
|
|
10
|
+
from blue_options.logger import crash_report
|
|
11
|
+
|
|
12
|
+
from bluer_objects import file, path, NAME
|
|
13
|
+
from bluer_objects.env import (
|
|
14
|
+
ABCLI_OBJECT_ROOT,
|
|
15
|
+
ABCLI_AWS_S3_BUCKET_NAME,
|
|
16
|
+
ABCLI_AWS_REGION,
|
|
17
|
+
ABCLI_PATH_STATIC,
|
|
18
|
+
ABCLI_AWS_S3_PREFIX,
|
|
19
|
+
abcli_object_name,
|
|
20
|
+
)
|
|
21
|
+
from bluer_objects.logger import logger
|
|
22
|
+
|
|
23
|
+
NAME = module.name(__file__, NAME)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Storage:
|
|
27
|
+
def __init__(self, bucket_name=ABCLI_AWS_S3_BUCKET_NAME):
|
|
28
|
+
self.region = ABCLI_AWS_REGION
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
self.s3 = boto3.client("s3", region_name=self.region)
|
|
32
|
+
except:
|
|
33
|
+
assert False, f"{NAME}.Storage: failed."
|
|
34
|
+
|
|
35
|
+
self.bucket_name = bucket_name
|
|
36
|
+
|
|
37
|
+
assert self.create_bucket()
|
|
38
|
+
|
|
39
|
+
def create_bucket(
|
|
40
|
+
self,
|
|
41
|
+
bucket_name: str = "",
|
|
42
|
+
) -> bool:
|
|
43
|
+
if not bucket_name:
|
|
44
|
+
bucket_name = self.bucket_name
|
|
45
|
+
|
|
46
|
+
try:
|
|
47
|
+
if boto3.resource("s3").Bucket(bucket_name).creation_date is not None:
|
|
48
|
+
logger.debug(f"-storage: create_bucket: {bucket_name}: already exists.")
|
|
49
|
+
return True
|
|
50
|
+
|
|
51
|
+
self.s3.create_bucket(
|
|
52
|
+
Bucket=bucket_name,
|
|
53
|
+
CreateBucketConfiguration={"LocationConstraint": self.region},
|
|
54
|
+
)
|
|
55
|
+
except:
|
|
56
|
+
crash_report(f"-storage: create_bucket: {bucket_name}: failed.")
|
|
57
|
+
return False
|
|
58
|
+
|
|
59
|
+
return True
|
|
60
|
+
|
|
61
|
+
def download_file(
|
|
62
|
+
self,
|
|
63
|
+
object_name: str,
|
|
64
|
+
filename: str = "",
|
|
65
|
+
bucket_name: Union[None, str] = None,
|
|
66
|
+
ignore_error: bool = False,
|
|
67
|
+
log: bool = True,
|
|
68
|
+
overwrite: bool = False,
|
|
69
|
+
) -> bool:
|
|
70
|
+
if filename == "static":
|
|
71
|
+
filename = os.path.join(
|
|
72
|
+
ABCLI_PATH_STATIC,
|
|
73
|
+
object_name.replace("/", "-"),
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
if filename == "object":
|
|
77
|
+
filename = os.path.join(
|
|
78
|
+
ABCLI_OBJECT_ROOT,
|
|
79
|
+
"/".join(object_name.split("/")[1:]),
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
if not overwrite and file.exists(filename):
|
|
83
|
+
if log:
|
|
84
|
+
logger.info(f"✅ {filename}")
|
|
85
|
+
return True
|
|
86
|
+
|
|
87
|
+
if not path.create(file.path(filename)):
|
|
88
|
+
return False
|
|
89
|
+
|
|
90
|
+
if bucket_name is None:
|
|
91
|
+
bucket_name = self.bucket_name
|
|
92
|
+
|
|
93
|
+
success = True
|
|
94
|
+
try:
|
|
95
|
+
self.s3.download_file(bucket_name, object_name, filename)
|
|
96
|
+
except:
|
|
97
|
+
success = False
|
|
98
|
+
|
|
99
|
+
message = "{}.Storage.downloaded_file: {}/{} -> {}".format(
|
|
100
|
+
NAME,
|
|
101
|
+
bucket_name,
|
|
102
|
+
object_name,
|
|
103
|
+
filename,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
if not success:
|
|
107
|
+
crash_report(f"{message}: failed.")
|
|
108
|
+
elif log:
|
|
109
|
+
logger.info(message)
|
|
110
|
+
|
|
111
|
+
return success
|
|
112
|
+
|
|
113
|
+
def list_of_objects(
|
|
114
|
+
self,
|
|
115
|
+
prefix: str,
|
|
116
|
+
bucket_name: Union[None, str] = None,
|
|
117
|
+
count: int = -1,
|
|
118
|
+
suffix: str = "",
|
|
119
|
+
recursive: bool = True,
|
|
120
|
+
include_folders: bool = False,
|
|
121
|
+
):
|
|
122
|
+
prefix = f"{ABCLI_AWS_S3_PREFIX}/{prefix}"
|
|
123
|
+
|
|
124
|
+
if bucket_name is None:
|
|
125
|
+
bucket_name = self.bucket_name
|
|
126
|
+
|
|
127
|
+
output = []
|
|
128
|
+
try:
|
|
129
|
+
output = [
|
|
130
|
+
string.after(object_summary.key, prefix)
|
|
131
|
+
for object_summary in boto3.resource("s3")
|
|
132
|
+
.Bucket(bucket_name)
|
|
133
|
+
.objects.filter(Prefix=prefix)
|
|
134
|
+
# .limit(count)
|
|
135
|
+
]
|
|
136
|
+
except:
|
|
137
|
+
crash_report("-storage: list_of_objects: failed.")
|
|
138
|
+
|
|
139
|
+
output = [thing[1:] if thing.startswith("/") else thing for thing in output]
|
|
140
|
+
|
|
141
|
+
if include_folders:
|
|
142
|
+
output = sorted(list({thing.split("/")[0] for thing in output}))
|
|
143
|
+
elif not recursive:
|
|
144
|
+
output = [thing for thing in output if "/" not in thing]
|
|
145
|
+
|
|
146
|
+
if suffix:
|
|
147
|
+
output = [thing for thing in output if thing.endswith(suffix)]
|
|
148
|
+
|
|
149
|
+
if count != -1:
|
|
150
|
+
output = output[:count]
|
|
151
|
+
|
|
152
|
+
return output
|
|
153
|
+
|
|
154
|
+
def exists(
|
|
155
|
+
self,
|
|
156
|
+
object_name: str,
|
|
157
|
+
bucket_name: Union[None, str] = None,
|
|
158
|
+
) -> bool:
|
|
159
|
+
if bucket_name is None:
|
|
160
|
+
bucket_name = self.bucket_name
|
|
161
|
+
|
|
162
|
+
try:
|
|
163
|
+
boto3.resource("s3").Object(
|
|
164
|
+
bucket_name, "/".join([ABCLI_AWS_S3_PREFIX, object_name])
|
|
165
|
+
).load()
|
|
166
|
+
except botocore.exceptions.ClientError as e:
|
|
167
|
+
if e.response["Error"]["Code"] != "404":
|
|
168
|
+
crash_report("-storage: exists: failed.")
|
|
169
|
+
return False
|
|
170
|
+
|
|
171
|
+
return True
|
|
172
|
+
|
|
173
|
+
def upload_file(
|
|
174
|
+
self,
|
|
175
|
+
filename: str,
|
|
176
|
+
object_name: Union[None, str] = None,
|
|
177
|
+
bucket_name: Union[None, str] = None,
|
|
178
|
+
overwrite: bool = False,
|
|
179
|
+
) -> Tuple[bool, str, str]:
|
|
180
|
+
if bucket_name is None:
|
|
181
|
+
bucket_name = self.bucket_name
|
|
182
|
+
|
|
183
|
+
if not filename:
|
|
184
|
+
logger.warning(f"{NAME}: Storage: upload_file(): upload_file: no file.")
|
|
185
|
+
return False, bucket_name, ""
|
|
186
|
+
|
|
187
|
+
if object_name is None:
|
|
188
|
+
object_name = "{}/{}{}".format(
|
|
189
|
+
ABCLI_AWS_S3_PREFIX,
|
|
190
|
+
abcli_object_name,
|
|
191
|
+
(
|
|
192
|
+
string.after(filename, abcli_object_name)
|
|
193
|
+
if abcli_object_name in filename
|
|
194
|
+
else filename
|
|
195
|
+
),
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
if not overwrite and self.exists(object_name):
|
|
199
|
+
logger.info(f"✅ {object_name}.")
|
|
200
|
+
return True, bucket_name, object_name
|
|
201
|
+
|
|
202
|
+
success = True
|
|
203
|
+
time_ = time.time()
|
|
204
|
+
try:
|
|
205
|
+
self.s3.upload_file(filename, bucket_name, object_name)
|
|
206
|
+
except:
|
|
207
|
+
success = False
|
|
208
|
+
duration = time.time() - time_
|
|
209
|
+
|
|
210
|
+
message = "{}.Storage.download_file: {}:{} -> {}/{}: {}.".format(
|
|
211
|
+
NAME,
|
|
212
|
+
filename,
|
|
213
|
+
string.pretty_bytes(file.size(filename)),
|
|
214
|
+
bucket_name,
|
|
215
|
+
object_name,
|
|
216
|
+
string.pretty_duration(
|
|
217
|
+
duration,
|
|
218
|
+
include_ms=True,
|
|
219
|
+
short=True,
|
|
220
|
+
),
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
if not success:
|
|
224
|
+
crash_report(f"{message}: failed.")
|
|
225
|
+
else:
|
|
226
|
+
logger.info(message)
|
|
227
|
+
|
|
228
|
+
return success, bucket_name, object_name
|
|
229
|
+
|
|
230
|
+
def url(self, object_name: str, filename: str) -> str:
|
|
231
|
+
return "https://{}.s3.{}.amazonaws.com/{}/{}/{}".format(
|
|
232
|
+
self.bucket_name,
|
|
233
|
+
self.region,
|
|
234
|
+
ABCLI_AWS_S3_PREFIX,
|
|
235
|
+
object_name,
|
|
236
|
+
filename,
|
|
237
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from abcli.tests.test_env import test_abcli_env
|
|
2
|
+
|
|
3
|
+
from bluer_objects import env
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_required_env():
|
|
7
|
+
test_abcli_env()
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_bluer_objects_env():
|
|
11
|
+
assert env.ABCLI_PUBLIC_PREFIX
|
|
12
|
+
assert env.VANWATCH_TEST_OBJECT
|
|
13
|
+
|
|
14
|
+
assert env.DATABRICKS_WORKSPACE
|
|
15
|
+
assert env.DATABRICKS_HOST
|
|
16
|
+
assert env.DATABRICKS_TOKEN
|
|
17
|
+
|
|
18
|
+
assert env.ABCLI_MLFLOW_EXPERIMENT_PREFIX
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_bluer_objects_env_RDS():
|
|
22
|
+
assert env.ABCLI_AWS_RDS_DB
|
|
23
|
+
assert env.ABCLI_AWS_RDS_PORT
|
|
24
|
+
assert env.ABCLI_AWS_RDS_USER
|
|
25
|
+
|
|
26
|
+
assert env.ABCLI_AWS_RDS_HOST
|
|
27
|
+
assert env.ABCLI_AWS_RDS_PASSWORD
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from typing import Callable, Union, Tuple, List
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from blue_options import string
|
|
6
|
+
|
|
7
|
+
from bluer_objects import file, objects, env
|
|
8
|
+
from bluer_objects.file.load import (
|
|
9
|
+
load_image,
|
|
10
|
+
load_json,
|
|
11
|
+
load_matrix,
|
|
12
|
+
load_text,
|
|
13
|
+
)
|
|
14
|
+
from bluer_objects.file.save import (
|
|
15
|
+
save_image,
|
|
16
|
+
save_json,
|
|
17
|
+
save_matrix,
|
|
18
|
+
save_text,
|
|
19
|
+
)
|
|
20
|
+
from bluer_objects.tests.test_objects import test_object
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@pytest.mark.parametrize(
|
|
24
|
+
[
|
|
25
|
+
"load_func",
|
|
26
|
+
"filename",
|
|
27
|
+
"save_func",
|
|
28
|
+
],
|
|
29
|
+
[
|
|
30
|
+
[
|
|
31
|
+
load_image,
|
|
32
|
+
"Victoria41East.jpg",
|
|
33
|
+
save_image,
|
|
34
|
+
],
|
|
35
|
+
[
|
|
36
|
+
load_json,
|
|
37
|
+
"vancouver.json",
|
|
38
|
+
save_json,
|
|
39
|
+
],
|
|
40
|
+
[
|
|
41
|
+
load_text,
|
|
42
|
+
"vancouver.json",
|
|
43
|
+
save_text,
|
|
44
|
+
],
|
|
45
|
+
],
|
|
46
|
+
)
|
|
47
|
+
def test_file_load_save(
|
|
48
|
+
test_object,
|
|
49
|
+
load_func: Callable,
|
|
50
|
+
filename: str,
|
|
51
|
+
save_func: Union[Callable, None],
|
|
52
|
+
):
|
|
53
|
+
success, thing = load_func(
|
|
54
|
+
objects.path_of(
|
|
55
|
+
object_name=test_object,
|
|
56
|
+
filename=filename,
|
|
57
|
+
)
|
|
58
|
+
)
|
|
59
|
+
assert success
|
|
60
|
+
|
|
61
|
+
if not save_func is None:
|
|
62
|
+
assert save_func(
|
|
63
|
+
file.add_suffix(
|
|
64
|
+
objects.path_of(
|
|
65
|
+
object_name=test_object,
|
|
66
|
+
filename=filename,
|
|
67
|
+
),
|
|
68
|
+
string.random(),
|
|
69
|
+
),
|
|
70
|
+
thing,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@pytest.mark.unit
|
|
75
|
+
@pytest.mark.parametrize(
|
|
76
|
+
["size", "dtype"],
|
|
77
|
+
[
|
|
78
|
+
[(10, 3), np.uint8],
|
|
79
|
+
[(10, 3), np.float16],
|
|
80
|
+
[(10, 20, 30), np.uint8],
|
|
81
|
+
[(10, 30, 20), np.uint8],
|
|
82
|
+
[(10, 30, 20), np.float32],
|
|
83
|
+
[(10, 10, 10, 5), np.uint8],
|
|
84
|
+
],
|
|
85
|
+
)
|
|
86
|
+
def test_file_load_save_matrix(
|
|
87
|
+
size: Tuple[int, ...],
|
|
88
|
+
dtype: Union[np.dtype, type],
|
|
89
|
+
) -> None:
|
|
90
|
+
object_name = objects.unique_object(test_file_load_save_matrix)
|
|
91
|
+
|
|
92
|
+
test_matrix = (
|
|
93
|
+
np.random.randint(0, 256, size=size, dtype=dtype)
|
|
94
|
+
if dtype == np.uint8
|
|
95
|
+
else np.array(np.random.random(size), dtype=dtype)
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
filename = objects.path_of("test.npy", object_name)
|
|
99
|
+
|
|
100
|
+
assert save_matrix(filename, test_matrix)
|
|
101
|
+
|
|
102
|
+
success, matrix_read = load_matrix(filename)
|
|
103
|
+
assert success
|
|
104
|
+
assert (matrix_read == test_matrix).all()
|
|
105
|
+
assert matrix_read.dtype == dtype
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from blueness import module
|
|
4
|
+
|
|
5
|
+
from bluer_objects import file, objects, NAME
|
|
6
|
+
from bluer_objects.env import VANWATCH_TEST_OBJECT
|
|
7
|
+
from bluer_objects.logger import logger
|
|
8
|
+
|
|
9
|
+
NAME = module.name(__file__, NAME)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@pytest.fixture
|
|
13
|
+
def test_image():
|
|
14
|
+
object_name = VANWATCH_TEST_OBJECT
|
|
15
|
+
|
|
16
|
+
assert objects.download(object_name)
|
|
17
|
+
|
|
18
|
+
success, matrix = file.load_image(
|
|
19
|
+
objects.path_of(
|
|
20
|
+
"Victoria41East.jpg",
|
|
21
|
+
object_name,
|
|
22
|
+
)
|
|
23
|
+
)
|
|
24
|
+
assert success
|
|
25
|
+
|
|
26
|
+
yield matrix
|
|
27
|
+
|
|
28
|
+
logger.info(f"deleting {NAME}.test_object ...")
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from bluer_objects.graphics.frame import add_frame
|
|
4
|
+
from bluer_objects.tests.test_graphics import test_image
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_graphics_frame_add_frame(test_image):
|
|
8
|
+
assert isinstance(
|
|
9
|
+
add_frame(test_image, width=12),
|
|
10
|
+
np.ndarray,
|
|
11
|
+
)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import glob
|
|
3
|
+
|
|
4
|
+
from bluer_objects import objects
|
|
5
|
+
from bluer_objects.graphics.gif import generate_animated_gif
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@pytest.mark.parametrize(
|
|
9
|
+
["object_name", "scale"],
|
|
10
|
+
[
|
|
11
|
+
["void", 1],
|
|
12
|
+
["2024-05-07-18-45-13-31678", 2],
|
|
13
|
+
],
|
|
14
|
+
)
|
|
15
|
+
def test_graphics_gif_generate_animated_gif(
|
|
16
|
+
object_name: str,
|
|
17
|
+
scale: int,
|
|
18
|
+
):
|
|
19
|
+
assert objects.download(object_name)
|
|
20
|
+
|
|
21
|
+
list_of_images = list(glob.glob(objects.path_of("*.png", object_name)))
|
|
22
|
+
if object_name != "void":
|
|
23
|
+
assert list_of_images
|
|
24
|
+
|
|
25
|
+
assert generate_animated_gif(
|
|
26
|
+
list_of_images,
|
|
27
|
+
objects.path_of("test.gif", object_name),
|
|
28
|
+
scale=scale,
|
|
29
|
+
)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from typing import Union, List
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from blue_options import string
|
|
6
|
+
|
|
7
|
+
from bluer_objects.env import DUMMY_TEXT
|
|
8
|
+
from bluer_objects.graphics.signature import add_signature, justify_text
|
|
9
|
+
from bluer_objects.tests.test_graphics import test_image
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@pytest.mark.parametrize(
|
|
13
|
+
["line_width"],
|
|
14
|
+
[
|
|
15
|
+
[10],
|
|
16
|
+
[80],
|
|
17
|
+
],
|
|
18
|
+
)
|
|
19
|
+
@pytest.mark.parametrize(
|
|
20
|
+
["word_wrap"],
|
|
21
|
+
[
|
|
22
|
+
[True],
|
|
23
|
+
[False],
|
|
24
|
+
],
|
|
25
|
+
)
|
|
26
|
+
def test_graphics_signature_add_signature(
|
|
27
|
+
line_width: int,
|
|
28
|
+
word_wrap: bool,
|
|
29
|
+
test_image,
|
|
30
|
+
):
|
|
31
|
+
assert isinstance(
|
|
32
|
+
add_signature(
|
|
33
|
+
test_image,
|
|
34
|
+
header=[DUMMY_TEXT],
|
|
35
|
+
footer=[DUMMY_TEXT, DUMMY_TEXT],
|
|
36
|
+
word_wrap=word_wrap,
|
|
37
|
+
line_width=line_width,
|
|
38
|
+
),
|
|
39
|
+
np.ndarray,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@pytest.mark.parametrize(
|
|
44
|
+
["text"],
|
|
45
|
+
[
|
|
46
|
+
[string.random(length=800)],
|
|
47
|
+
[[string.random(length=120) for _ in range(3)]],
|
|
48
|
+
],
|
|
49
|
+
)
|
|
50
|
+
@pytest.mark.parametrize(
|
|
51
|
+
["line_width"],
|
|
52
|
+
[
|
|
53
|
+
[80],
|
|
54
|
+
],
|
|
55
|
+
)
|
|
56
|
+
@pytest.mark.parametrize(
|
|
57
|
+
["return_str"],
|
|
58
|
+
[
|
|
59
|
+
[True],
|
|
60
|
+
[False],
|
|
61
|
+
],
|
|
62
|
+
)
|
|
63
|
+
def test_justify_text(
|
|
64
|
+
text: Union[str, List[str]],
|
|
65
|
+
line_width: int,
|
|
66
|
+
return_str: bool,
|
|
67
|
+
):
|
|
68
|
+
justified_text = justify_text(
|
|
69
|
+
text,
|
|
70
|
+
line_width=line_width,
|
|
71
|
+
return_str=return_str,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
if return_str:
|
|
75
|
+
assert isinstance(justified_text, str)
|
|
76
|
+
else:
|
|
77
|
+
assert isinstance(justified_text, list)
|
|
78
|
+
|
|
79
|
+
for line in justified_text:
|
|
80
|
+
assert len(line) <= line_width, f'len("{line}") > {line_width}'
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from bluer_objects.graphics.text import render_text
|
|
4
|
+
from bluer_objects.env import DUMMY_TEXT
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_graphics_text_render_text():
|
|
8
|
+
assert isinstance(
|
|
9
|
+
render_text(
|
|
10
|
+
text=[DUMMY_TEXT for _ in range(10)],
|
|
11
|
+
image_width=1024,
|
|
12
|
+
),
|
|
13
|
+
np.ndarray,
|
|
14
|
+
)
|