bluer-objects 6.377.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.
- bluer_objects/.abcli/alias.sh +8 -12
- bluer_objects/.abcli/assets/cd.sh +1 -1
- bluer_objects/.abcli/assets/mv.sh +6 -6
- bluer_objects/.abcli/assets/publish.sh +4 -1
- bluer_objects/.abcli/mlflow/tags/search.sh +1 -5
- bluer_objects/.abcli/tests/help.sh +0 -7
- bluer_objects/.abcli/tests/mlflow_tags.sh +1 -1
- bluer_objects/.abcli/tests/pdf.sh +10 -2
- bluer_objects/README/__init__.py +7 -37
- bluer_objects/README/alias.py +15 -4
- bluer_objects/README/build/__init__.py +0 -0
- bluer_objects/README/build/aliases.py +23 -0
- bluer_objects/README/build/docs.py +23 -0
- bluer_objects/README/build/modules.py +9 -0
- bluer_objects/README/consts.py +8 -3
- bluer_objects/README/functions.py +50 -22
- bluer_objects/README/process/__init__.py +0 -0
- bluer_objects/README/process/assets.py +36 -0
- bluer_objects/README/process/details.py +20 -0
- bluer_objects/README/process/envs.py +23 -0
- bluer_objects/README/process/help.py +27 -0
- bluer_objects/README/process/include.py +40 -0
- bluer_objects/README/process/legacy.py +21 -0
- bluer_objects/README/process/mermaid.py +20 -0
- bluer_objects/README/process/national_internet.py +55 -0
- bluer_objects/README/process/objects.py +32 -0
- bluer_objects/README/process/signature.py +35 -0
- bluer_objects/README/process/title.py +44 -0
- bluer_objects/README/process/variables.py +12 -0
- bluer_objects/__init__.py +1 -1
- bluer_objects/config.env +8 -4
- bluer_objects/env.py +4 -1
- bluer_objects/file/functions.py +8 -1
- bluer_objects/help/assets.py +6 -9
- bluer_objects/help/functions.py +0 -2
- bluer_objects/help/mlflow/cache.py +2 -4
- bluer_objects/help/mlflow/tags.py +34 -23
- bluer_objects/mlflow/__init__.py +1 -1
- bluer_objects/mlflow/__main__.py +49 -31
- bluer_objects/mlflow/lock/functions.py +1 -1
- bluer_objects/mlflow/logging.py +6 -0
- bluer_objects/mlflow/models.py +7 -0
- bluer_objects/mlflow/objects.py +7 -0
- bluer_objects/mlflow/runs.py +10 -1
- bluer_objects/mlflow/serverless/__init__.py +3 -0
- bluer_objects/mlflow/serverless/api.py +88 -0
- bluer_objects/mlflow/serverless/read.py +19 -0
- bluer_objects/mlflow/serverless/search.py +35 -0
- bluer_objects/mlflow/serverless/write.py +42 -0
- bluer_objects/mlflow/tags.py +59 -9
- bluer_objects/objects.py +3 -1
- bluer_objects/pdf/convert/convert.py +1 -2
- bluer_objects/tests/test_env.py +34 -22
- bluer_objects/tests/test_file_download.py +5 -0
- bluer_objects/tests/test_mlflow.py +112 -3
- bluer_objects/tests/test_web_is_accessible.py +1 -1
- {bluer_objects-6.377.1.dist-info → bluer_objects-6.464.1.dist-info}/METADATA +19 -13
- {bluer_objects-6.377.1.dist-info → bluer_objects-6.464.1.dist-info}/RECORD +61 -50
- {bluer_objects-6.377.1.dist-info → bluer_objects-6.464.1.dist-info}/WHEEL +1 -1
- bluer_objects/.abcli/tests/mlflow_test.sh +0 -7
- bluer_objects/.abcli/tests/web_is_accessible.sh +0 -17
- bluer_objects/.abcli/tests/web_where_am_ai.sh +0 -5
- bluer_objects/.abcli/url.sh +0 -15
- bluer_objects/.abcli/web/is_accessible.sh +0 -13
- bluer_objects/.abcli/web/where_am_i.sh +0 -5
- bluer_objects/README/utils.py +0 -275
- bluer_objects/help/web.py +0 -38
- bluer_objects/web/__init__.py +0 -1
- bluer_objects/web/__main__.py +0 -31
- bluer_objects/web/functions.py +0 -9
- {bluer_objects-6.377.1.dist-info → bluer_objects-6.464.1.dist-info}/licenses/LICENSE +0 -0
- {bluer_objects-6.377.1.dist-info → bluer_objects-6.464.1.dist-info}/top_level.txt +0 -0
bluer_objects/mlflow/objects.py
CHANGED
|
@@ -6,6 +6,7 @@ from blueness import module
|
|
|
6
6
|
from bluer_options.logger import crash_report
|
|
7
7
|
|
|
8
8
|
from bluer_objects import NAME
|
|
9
|
+
from bluer_objects import env
|
|
9
10
|
from bluer_objects.env import ABCLI_MLFLOW_EXPERIMENT_PREFIX
|
|
10
11
|
from bluer_objects.logger import logger
|
|
11
12
|
|
|
@@ -16,6 +17,9 @@ def get_id(
|
|
|
16
17
|
object_name: str,
|
|
17
18
|
create: bool = False,
|
|
18
19
|
) -> Tuple[bool, str]:
|
|
20
|
+
if env.MLFLOW_IS_SERVERLESS:
|
|
21
|
+
return True, "serverless-id"
|
|
22
|
+
|
|
19
23
|
experiment_name = to_experiment_name(object_name)
|
|
20
24
|
|
|
21
25
|
try:
|
|
@@ -38,6 +42,9 @@ def rm(
|
|
|
38
42
|
object_name: str,
|
|
39
43
|
is_id: bool = False,
|
|
40
44
|
) -> bool:
|
|
45
|
+
if env.MLFLOW_IS_SERVERLESS:
|
|
46
|
+
return True
|
|
47
|
+
|
|
41
48
|
if is_id:
|
|
42
49
|
experiment_id = object_name
|
|
43
50
|
else:
|
bluer_objects/mlflow/runs.py
CHANGED
|
@@ -5,10 +5,10 @@ from mlflow.tracking import MlflowClient
|
|
|
5
5
|
from mlflow.entities import ViewType
|
|
6
6
|
|
|
7
7
|
from blueness import module
|
|
8
|
-
from bluer_options import string
|
|
9
8
|
from bluer_options.logger import crash_report
|
|
10
9
|
|
|
11
10
|
from bluer_objects import NAME
|
|
11
|
+
from bluer_objects import env
|
|
12
12
|
from bluer_objects.mlflow.objects import get_id
|
|
13
13
|
from bluer_objects.mlflow.tags import get_tags
|
|
14
14
|
from bluer_objects.logger import logger
|
|
@@ -19,6 +19,9 @@ NAME = module.name(__file__, NAME)
|
|
|
19
19
|
def end_run(
|
|
20
20
|
object_name: str,
|
|
21
21
|
) -> bool:
|
|
22
|
+
if env.MLFLOW_IS_SERVERLESS:
|
|
23
|
+
return True
|
|
24
|
+
|
|
22
25
|
try:
|
|
23
26
|
mlflow.end_run()
|
|
24
27
|
logger.info("⏹️ {}".format(object_name))
|
|
@@ -36,6 +39,9 @@ def get_run_id(
|
|
|
36
39
|
create: bool = False,
|
|
37
40
|
is_id: bool = False,
|
|
38
41
|
) -> Tuple[bool, List[str]]:
|
|
42
|
+
if env.MLFLOW_IS_SERVERLESS:
|
|
43
|
+
return True, []
|
|
44
|
+
|
|
39
45
|
if is_id:
|
|
40
46
|
experiment_id = object_name
|
|
41
47
|
else:
|
|
@@ -62,6 +68,9 @@ def get_run_id(
|
|
|
62
68
|
def start_run(
|
|
63
69
|
object_name: str,
|
|
64
70
|
) -> bool:
|
|
71
|
+
if env.MLFLOW_IS_SERVERLESS:
|
|
72
|
+
return True
|
|
73
|
+
|
|
65
74
|
success, experiment_id = get_id(object_name, create=True)
|
|
66
75
|
if not success:
|
|
67
76
|
return False
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
from typing import Dict, Tuple
|
|
2
|
+
|
|
3
|
+
from blueness import module
|
|
4
|
+
|
|
5
|
+
from bluer_objects import NAME
|
|
6
|
+
from bluer_objects import file
|
|
7
|
+
from bluer_objects import objects
|
|
8
|
+
from bluer_objects import storage
|
|
9
|
+
from bluer_objects.logger import logger
|
|
10
|
+
|
|
11
|
+
NAME = module.name(__file__, NAME)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def write(
|
|
15
|
+
object_name: str,
|
|
16
|
+
filename: str,
|
|
17
|
+
data: Dict,
|
|
18
|
+
log: bool = False,
|
|
19
|
+
) -> bool:
|
|
20
|
+
if log:
|
|
21
|
+
logger.info(f"{NAME}.update({object_name}/{filename})")
|
|
22
|
+
|
|
23
|
+
if not storage.download(
|
|
24
|
+
object_name=object_name,
|
|
25
|
+
filename=filename,
|
|
26
|
+
log=log,
|
|
27
|
+
):
|
|
28
|
+
return False
|
|
29
|
+
|
|
30
|
+
full_filename = objects.path_of(
|
|
31
|
+
object_name=object_name,
|
|
32
|
+
filename=filename,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
_, current_data = file.load_yaml(
|
|
36
|
+
full_filename,
|
|
37
|
+
ignore_error=True,
|
|
38
|
+
default={},
|
|
39
|
+
)
|
|
40
|
+
if not isinstance(current_data, dict):
|
|
41
|
+
logger.error(
|
|
42
|
+
"dict expected, {} received".format(
|
|
43
|
+
current_data.__class__.__name__,
|
|
44
|
+
)
|
|
45
|
+
)
|
|
46
|
+
return False
|
|
47
|
+
|
|
48
|
+
current_data.update(data)
|
|
49
|
+
|
|
50
|
+
if not file.save_yaml(
|
|
51
|
+
full_filename,
|
|
52
|
+
current_data,
|
|
53
|
+
log=log,
|
|
54
|
+
):
|
|
55
|
+
return False
|
|
56
|
+
|
|
57
|
+
if not storage.upload(
|
|
58
|
+
object_name=object_name,
|
|
59
|
+
filename=filename,
|
|
60
|
+
log=log,
|
|
61
|
+
):
|
|
62
|
+
return False
|
|
63
|
+
|
|
64
|
+
return True
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def read(
|
|
68
|
+
object_name: str,
|
|
69
|
+
filename: str,
|
|
70
|
+
verbose: bool = False,
|
|
71
|
+
) -> Tuple[bool, Dict]:
|
|
72
|
+
if not storage.download(
|
|
73
|
+
object_name=object_name,
|
|
74
|
+
filename=filename,
|
|
75
|
+
log=verbose,
|
|
76
|
+
):
|
|
77
|
+
return True, {}
|
|
78
|
+
|
|
79
|
+
_, data = file.load_yaml(
|
|
80
|
+
objects.path_of(
|
|
81
|
+
object_name=object_name,
|
|
82
|
+
filename=filename,
|
|
83
|
+
),
|
|
84
|
+
ignore_error=True,
|
|
85
|
+
default={},
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
return True, data
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from typing import Tuple, Dict
|
|
2
|
+
|
|
3
|
+
from blueness import module
|
|
4
|
+
|
|
5
|
+
from bluer_objects import NAME
|
|
6
|
+
from bluer_objects.mlflow.serverless import api
|
|
7
|
+
|
|
8
|
+
NAME = module.name(__file__, NAME)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_tags(
|
|
12
|
+
object_name: str,
|
|
13
|
+
verbose: bool = False,
|
|
14
|
+
) -> Tuple[bool, Dict[str, str]]:
|
|
15
|
+
return api.read(
|
|
16
|
+
object_name="_serverless_objects",
|
|
17
|
+
filename=f"{object_name}.yaml",
|
|
18
|
+
verbose=verbose,
|
|
19
|
+
)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from typing import List, Tuple, Union
|
|
2
|
+
|
|
3
|
+
from bluer_options.options import Options
|
|
4
|
+
|
|
5
|
+
from bluer_objects.mlflow.serverless import api
|
|
6
|
+
from bluer_objects.logger import logger
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def search(
|
|
10
|
+
filter_string: Union[str, dict],
|
|
11
|
+
log: bool = False,
|
|
12
|
+
) -> Tuple[bool, List[str]]:
|
|
13
|
+
query = Options(filter_string)
|
|
14
|
+
|
|
15
|
+
output: Union[List[str], None] = None
|
|
16
|
+
for key, value in query.items():
|
|
17
|
+
success, dict_of_objects = api.read(
|
|
18
|
+
object_name="_serverless_keys",
|
|
19
|
+
filename=f"{key}.yaml",
|
|
20
|
+
verbose=log,
|
|
21
|
+
)
|
|
22
|
+
if not success:
|
|
23
|
+
return False, []
|
|
24
|
+
|
|
25
|
+
output = [
|
|
26
|
+
object_name
|
|
27
|
+
for object_name in (dict_of_objects if output is None else output)
|
|
28
|
+
if dict_of_objects.get(
|
|
29
|
+
object_name,
|
|
30
|
+
False if isinstance(value, bool) else None,
|
|
31
|
+
)
|
|
32
|
+
== value
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
return True, [] if output is None else output
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from typing import Dict, Union
|
|
2
|
+
|
|
3
|
+
from blueness import module
|
|
4
|
+
from bluer_options.options import Options
|
|
5
|
+
|
|
6
|
+
from bluer_objects import NAME
|
|
7
|
+
from bluer_objects.mlflow.serverless import api
|
|
8
|
+
from bluer_objects.logger import logger
|
|
9
|
+
|
|
10
|
+
NAME = module.name(__file__, NAME)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def set_tags(
|
|
14
|
+
object_name: str,
|
|
15
|
+
tags: Union[str, Dict[str, str]],
|
|
16
|
+
log: bool = True,
|
|
17
|
+
verbose: bool = False,
|
|
18
|
+
icon="#️⃣ ",
|
|
19
|
+
) -> bool:
|
|
20
|
+
tags = Options(tags)
|
|
21
|
+
|
|
22
|
+
if not api.write(
|
|
23
|
+
object_name="_serverless_objects",
|
|
24
|
+
filename=f"{object_name}.yaml",
|
|
25
|
+
data=tags,
|
|
26
|
+
log=verbose,
|
|
27
|
+
):
|
|
28
|
+
return False
|
|
29
|
+
|
|
30
|
+
for key, value in tags.items():
|
|
31
|
+
if not api.write(
|
|
32
|
+
object_name="_serverless_keys",
|
|
33
|
+
filename=f"{key}.yaml",
|
|
34
|
+
data={object_name: value},
|
|
35
|
+
log=verbose,
|
|
36
|
+
):
|
|
37
|
+
return False
|
|
38
|
+
|
|
39
|
+
if log:
|
|
40
|
+
logger.info("{} {}.{}={}".format(icon, object_name, key, value))
|
|
41
|
+
|
|
42
|
+
return True
|
bluer_objects/mlflow/tags.py
CHANGED
|
@@ -7,13 +7,17 @@ from bluer_options.options import Options
|
|
|
7
7
|
from bluer_options.logger import crash_report
|
|
8
8
|
|
|
9
9
|
from bluer_objects import NAME
|
|
10
|
+
from bluer_objects import env
|
|
11
|
+
from bluer_objects.mlflow import serverless
|
|
10
12
|
from bluer_objects.mlflow.objects import to_experiment_name, to_object_name
|
|
11
13
|
from bluer_objects.logger import logger
|
|
12
14
|
|
|
13
15
|
NAME = module.name(__file__, NAME)
|
|
14
16
|
|
|
15
17
|
|
|
16
|
-
def
|
|
18
|
+
def create_server_style_filter_string(
|
|
19
|
+
tags: Union[str, dict],
|
|
20
|
+
) -> str:
|
|
17
21
|
tags_options = Options(tags)
|
|
18
22
|
|
|
19
23
|
# https://www.mlflow.org/docs/latest/search-experiments.html
|
|
@@ -25,7 +29,14 @@ def create_filter_string(tags: str) -> str:
|
|
|
25
29
|
def get_tags(
|
|
26
30
|
object_name: str,
|
|
27
31
|
exclude_system_tags: bool = True,
|
|
32
|
+
verbose: bool = False,
|
|
28
33
|
) -> Tuple[bool, Dict[str, str]]:
|
|
34
|
+
if env.MLFLOW_IS_SERVERLESS:
|
|
35
|
+
return serverless.get_tags(
|
|
36
|
+
object_name,
|
|
37
|
+
verbose=verbose,
|
|
38
|
+
)
|
|
39
|
+
|
|
29
40
|
experiment_name = to_experiment_name(object_name)
|
|
30
41
|
|
|
31
42
|
try:
|
|
@@ -48,16 +59,45 @@ def get_tags(
|
|
|
48
59
|
|
|
49
60
|
|
|
50
61
|
# https://www.mlflow.org/docs/latest/search-experiments.html
|
|
51
|
-
def search(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
62
|
+
def search(
|
|
63
|
+
filter_string: Union[str, dict],
|
|
64
|
+
server_style: bool = False,
|
|
65
|
+
verbose: bool = False,
|
|
66
|
+
) -> Tuple[bool, List[str]]:
|
|
67
|
+
if server_style and env.MLFLOW_IS_SERVERLESS:
|
|
68
|
+
logger.error("server_style search is not supported when mlflow is serverless.")
|
|
69
|
+
return False, []
|
|
70
|
+
|
|
71
|
+
if filter_string == "-":
|
|
72
|
+
filter_string = ""
|
|
73
|
+
|
|
74
|
+
if env.MLFLOW_IS_SERVERLESS:
|
|
75
|
+
return serverless.search(
|
|
57
76
|
filter_string=filter_string,
|
|
58
|
-
|
|
77
|
+
log=verbose,
|
|
59
78
|
)
|
|
60
|
-
|
|
79
|
+
|
|
80
|
+
if not server_style:
|
|
81
|
+
filter_string = create_server_style_filter_string(filter_string)
|
|
82
|
+
|
|
83
|
+
client = MlflowClient()
|
|
84
|
+
|
|
85
|
+
success = False
|
|
86
|
+
output = []
|
|
87
|
+
|
|
88
|
+
try:
|
|
89
|
+
output = [
|
|
90
|
+
to_object_name(experiment.name)
|
|
91
|
+
for experiment in client.search_experiments(
|
|
92
|
+
filter_string=filter_string,
|
|
93
|
+
view_type=ViewType.ALL,
|
|
94
|
+
)
|
|
95
|
+
]
|
|
96
|
+
success = True
|
|
97
|
+
except Exception as e:
|
|
98
|
+
logger.error(e)
|
|
99
|
+
|
|
100
|
+
return success, output
|
|
61
101
|
|
|
62
102
|
|
|
63
103
|
def set_tags(
|
|
@@ -65,7 +105,17 @@ def set_tags(
|
|
|
65
105
|
tags: Union[str, Dict[str, str]],
|
|
66
106
|
log: bool = True,
|
|
67
107
|
icon="#️⃣ ",
|
|
108
|
+
verbose: bool = False,
|
|
68
109
|
) -> bool:
|
|
110
|
+
if env.MLFLOW_IS_SERVERLESS:
|
|
111
|
+
return serverless.set_tags(
|
|
112
|
+
object_name,
|
|
113
|
+
tags=tags,
|
|
114
|
+
log=log,
|
|
115
|
+
verbose=verbose,
|
|
116
|
+
icon=icon,
|
|
117
|
+
)
|
|
118
|
+
|
|
69
119
|
experiment_name = to_experiment_name(object_name)
|
|
70
120
|
|
|
71
121
|
try:
|
bluer_objects/objects.py
CHANGED
|
@@ -69,6 +69,7 @@ def signature(info=None, object_name="."):
|
|
|
69
69
|
def unique_object(
|
|
70
70
|
prefix: str = "",
|
|
71
71
|
include_time: bool = True,
|
|
72
|
+
log: bool = True,
|
|
72
73
|
):
|
|
73
74
|
object_name = string.pretty_date(
|
|
74
75
|
as_filename=True,
|
|
@@ -80,6 +81,7 @@ def unique_object(
|
|
|
80
81
|
|
|
81
82
|
path.create(object_path(object_name))
|
|
82
83
|
|
|
83
|
-
|
|
84
|
+
if log:
|
|
85
|
+
logger.info(f"📂 {object_name}")
|
|
84
86
|
|
|
85
87
|
return object_name
|
|
@@ -79,8 +79,7 @@ def convert(
|
|
|
79
79
|
):
|
|
80
80
|
return False
|
|
81
81
|
elif file.extension(source_filename) in [
|
|
82
|
-
extension.split(".", 1)[1]
|
|
83
|
-
for extension in Image.registered_extensions().keys()
|
|
82
|
+
extension.split(".", 1)[1] for extension in Image.registered_extensions()
|
|
84
83
|
]:
|
|
85
84
|
if not convert_image(
|
|
86
85
|
source_filename,
|
bluer_objects/tests/test_env.py
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
from bluer_options.testing import (
|
|
2
|
+
are_01,
|
|
3
|
+
are_positive_ints,
|
|
4
|
+
are_nonempty_strs,
|
|
5
|
+
)
|
|
1
6
|
from bluer_ai.tests.test_env import test_bluer_ai_env
|
|
2
7
|
|
|
3
8
|
from bluer_objects import env
|
|
@@ -14,14 +19,35 @@ def test_required_env():
|
|
|
14
19
|
|
|
15
20
|
|
|
16
21
|
def test_bluer_objects_env():
|
|
17
|
-
assert
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
assert
|
|
24
|
-
|
|
22
|
+
assert are_01(
|
|
23
|
+
[
|
|
24
|
+
env.MLFLOW_IS_SERVERLESS,
|
|
25
|
+
]
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
assert are_nonempty_strs(
|
|
29
|
+
[
|
|
30
|
+
env.ABCLI_MLFLOW_EXPERIMENT_PREFIX,
|
|
31
|
+
env.BLUER_OBJECTS_DEFAULT_ASSETS_VOL,
|
|
32
|
+
env.BLUER_OBJECTS_TEST_OBJECT,
|
|
33
|
+
env.MLFLOW_DEPLOYMENT,
|
|
34
|
+
env.S3_PUBLIC_STORAGE_BUCKET,
|
|
35
|
+
env.S3_STORAGE_AWS_ACCESS_KEY_ID,
|
|
36
|
+
env.S3_STORAGE_AWS_SECRET_ACCESS_KEY,
|
|
37
|
+
env.S3_STORAGE_BUCKET,
|
|
38
|
+
env.S3_STORAGE_ENDPOINT_URL,
|
|
39
|
+
env.WEBDAV_HOSTNAME,
|
|
40
|
+
env.WEBDAV_LOGIN,
|
|
41
|
+
env.WEBDAV_PASSWORD,
|
|
42
|
+
]
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
assert are_positive_ints(
|
|
46
|
+
[
|
|
47
|
+
env.MLFLOW_LOCK_WAIT_FOR_CLEARANCE,
|
|
48
|
+
env.MLFLOW_LOCK_WAIT_FOR_EXCLUSIVITY,
|
|
49
|
+
]
|
|
50
|
+
)
|
|
25
51
|
|
|
26
52
|
assert env.BLUER_OBJECTS_STORAGE_INTERFACE in [
|
|
27
53
|
S3Interface.name,
|
|
@@ -29,17 +55,3 @@ def test_bluer_objects_env():
|
|
|
29
55
|
WebDAVRequestInterface.name,
|
|
30
56
|
WebDAVzipInterface.name,
|
|
31
57
|
]
|
|
32
|
-
|
|
33
|
-
assert env.MLFLOW_DEPLOYMENT
|
|
34
|
-
|
|
35
|
-
assert isinstance(env.MLFLOW_LOCK_WAIT_FOR_CLEARANCE, int)
|
|
36
|
-
assert env.MLFLOW_LOCK_WAIT_FOR_CLEARANCE > 0
|
|
37
|
-
|
|
38
|
-
assert isinstance(env.MLFLOW_LOCK_WAIT_FOR_EXCLUSIVITY, int)
|
|
39
|
-
assert env.MLFLOW_LOCK_WAIT_FOR_EXCLUSIVITY > 0
|
|
40
|
-
|
|
41
|
-
assert env.WEBDAV_HOSTNAME
|
|
42
|
-
assert env.WEBDAV_LOGIN
|
|
43
|
-
assert env.WEBDAV_PASSWORD
|
|
44
|
-
|
|
45
|
-
assert env.BLUER_OBJECTS_TEST_OBJECT
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
|
|
3
|
+
from bluer_options.env import BLUER_AI_WEB_STATUS
|
|
4
|
+
|
|
3
5
|
from bluer_objects import objects, file
|
|
4
6
|
|
|
5
7
|
|
|
@@ -10,6 +12,9 @@ from bluer_objects import objects, file
|
|
|
10
12
|
],
|
|
11
13
|
)
|
|
12
14
|
def test_file_download(url: str):
|
|
15
|
+
if BLUER_AI_WEB_STATUS != "online":
|
|
16
|
+
return
|
|
17
|
+
|
|
13
18
|
object_name = objects.unique_object("test_file_download")
|
|
14
19
|
|
|
15
20
|
filename = objects.path_of(
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
|
|
3
|
-
from bluer_options.options import Options
|
|
4
3
|
from bluer_options import string
|
|
4
|
+
from bluer_options.options import Options
|
|
5
|
+
from bluer_options.testing import is_list_of_str
|
|
5
6
|
|
|
7
|
+
from bluer_objects import env
|
|
6
8
|
from bluer_objects.objects import unique_object
|
|
7
9
|
from bluer_objects.mlflow import cache
|
|
10
|
+
from bluer_objects.mlflow import create_server_style_filter_string
|
|
8
11
|
from bluer_objects.mlflow import objects
|
|
9
12
|
from bluer_objects.mlflow import tags
|
|
10
13
|
from bluer_objects.mlflow import testing
|
|
@@ -19,14 +22,32 @@ def test_from_and_to_experiment_name():
|
|
|
19
22
|
|
|
20
23
|
|
|
21
24
|
def test_mlflow_testing():
|
|
25
|
+
MLFLOW_IS_SERVERLESS = env.MLFLOW_IS_SERVERLESS
|
|
26
|
+
env.MLFLOW_IS_SERVERLESS = False
|
|
27
|
+
|
|
22
28
|
assert testing.test()
|
|
23
29
|
|
|
30
|
+
env.MLFLOW_IS_SERVERLESS = MLFLOW_IS_SERVERLESS
|
|
31
|
+
|
|
24
32
|
|
|
25
33
|
@pytest.mark.parametrize(
|
|
26
34
|
["tags_str"],
|
|
27
35
|
[["x=1,y=2,z=3"]],
|
|
28
36
|
)
|
|
29
|
-
|
|
37
|
+
@pytest.mark.parametrize(
|
|
38
|
+
["serverless"],
|
|
39
|
+
[
|
|
40
|
+
[False],
|
|
41
|
+
[True],
|
|
42
|
+
],
|
|
43
|
+
)
|
|
44
|
+
def test_mlflow_tags_set_get(
|
|
45
|
+
tags_str: str,
|
|
46
|
+
serverless: bool,
|
|
47
|
+
):
|
|
48
|
+
MLFLOW_IS_SERVERLESS = env.MLFLOW_IS_SERVERLESS
|
|
49
|
+
env.MLFLOW_IS_SERVERLESS = serverless
|
|
50
|
+
|
|
30
51
|
object_name = unique_object("test_mlflow_tag_set_get")
|
|
31
52
|
|
|
32
53
|
assert tags.set_tags(
|
|
@@ -42,6 +63,62 @@ def test_mlflow_tag_set_get(tags_str: str):
|
|
|
42
63
|
for keyword, value in tags_option.items():
|
|
43
64
|
assert tags_read[keyword] == value
|
|
44
65
|
|
|
66
|
+
env.MLFLOW_IS_SERVERLESS = MLFLOW_IS_SERVERLESS
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@pytest.mark.parametrize(
|
|
70
|
+
[
|
|
71
|
+
"filter_string",
|
|
72
|
+
"server_style",
|
|
73
|
+
"serverless",
|
|
74
|
+
"success_expected",
|
|
75
|
+
],
|
|
76
|
+
[
|
|
77
|
+
[
|
|
78
|
+
"this=that,what,~who",
|
|
79
|
+
False,
|
|
80
|
+
True,
|
|
81
|
+
True,
|
|
82
|
+
],
|
|
83
|
+
[
|
|
84
|
+
"this=that,what,~who",
|
|
85
|
+
False,
|
|
86
|
+
False,
|
|
87
|
+
True,
|
|
88
|
+
],
|
|
89
|
+
[
|
|
90
|
+
'tags."this" = "that" and tags."what" = "True" and tags."who" = "False"',
|
|
91
|
+
True,
|
|
92
|
+
True,
|
|
93
|
+
False,
|
|
94
|
+
],
|
|
95
|
+
[
|
|
96
|
+
'tags."this" = "that" and tags."what" = "True" and tags."who" = "False"',
|
|
97
|
+
True,
|
|
98
|
+
False,
|
|
99
|
+
True,
|
|
100
|
+
],
|
|
101
|
+
],
|
|
102
|
+
)
|
|
103
|
+
def test_mlflow_tags_search(
|
|
104
|
+
filter_string: str,
|
|
105
|
+
server_style: bool,
|
|
106
|
+
serverless: bool,
|
|
107
|
+
success_expected: bool,
|
|
108
|
+
):
|
|
109
|
+
MLFLOW_IS_SERVERLESS = env.MLFLOW_IS_SERVERLESS
|
|
110
|
+
env.MLFLOW_IS_SERVERLESS = serverless
|
|
111
|
+
|
|
112
|
+
success, list_of_objects = tags.search(
|
|
113
|
+
filter_string,
|
|
114
|
+
server_style=server_style,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
assert success == success_expected
|
|
118
|
+
assert is_list_of_str(list_of_objects)
|
|
119
|
+
|
|
120
|
+
env.MLFLOW_IS_SERVERLESS = MLFLOW_IS_SERVERLESS
|
|
121
|
+
|
|
45
122
|
|
|
46
123
|
@pytest.mark.parametrize(
|
|
47
124
|
["keyword", "value"],
|
|
@@ -52,9 +129,41 @@ def test_mlflow_tag_set_get(tags_str: str):
|
|
|
52
129
|
]
|
|
53
130
|
],
|
|
54
131
|
)
|
|
55
|
-
|
|
132
|
+
@pytest.mark.parametrize(
|
|
133
|
+
["serverless"],
|
|
134
|
+
[
|
|
135
|
+
[True],
|
|
136
|
+
[False],
|
|
137
|
+
],
|
|
138
|
+
)
|
|
139
|
+
def test_mlflow_cache_read_write(
|
|
140
|
+
keyword: str,
|
|
141
|
+
value: str,
|
|
142
|
+
serverless: bool,
|
|
143
|
+
):
|
|
144
|
+
MLFLOW_IS_SERVERLESS = env.MLFLOW_IS_SERVERLESS
|
|
145
|
+
env.MLFLOW_IS_SERVERLESS = serverless
|
|
146
|
+
|
|
56
147
|
assert cache.write(keyword, value)
|
|
57
148
|
|
|
58
149
|
success, value_read = cache.read(keyword)
|
|
59
150
|
assert success
|
|
60
151
|
assert value_read == value
|
|
152
|
+
|
|
153
|
+
env.MLFLOW_IS_SERVERLESS = MLFLOW_IS_SERVERLESS
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@pytest.mark.parametrize(
|
|
157
|
+
["filter_string", "expected_output"],
|
|
158
|
+
[
|
|
159
|
+
[
|
|
160
|
+
"this=that,what,~who",
|
|
161
|
+
'tags."this" = "that" and tags."what" = "True" and tags."who" = "False"',
|
|
162
|
+
]
|
|
163
|
+
],
|
|
164
|
+
)
|
|
165
|
+
def test_create_server_style_filter_string(
|
|
166
|
+
filter_string: str,
|
|
167
|
+
expected_output: str,
|
|
168
|
+
):
|
|
169
|
+
assert create_server_style_filter_string(filter_string) == expected_output
|