bluer-objects 6.166.1__py3-none-any.whl → 6.170.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/__init__.py CHANGED
@@ -4,7 +4,7 @@ ICON = "🌀"
4
4
 
5
5
  DESCRIPTION = f"{ICON} Object management in Bash."
6
6
 
7
- VERSION = "6.166.1"
7
+ VERSION = "6.170.1"
8
8
 
9
9
  REPO_NAME = "bluer-objects"
10
10
 
@@ -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)
@@ -0,0 +1,121 @@
1
+ import time
2
+
3
+ from blueness import module
4
+ from bluer_options import string
5
+
6
+ from bluer_objects import NAME, env
7
+ from bluer_objects.mlflow.tags import get_tags, set_tags
8
+ from bluer_objects.logger import logger
9
+
10
+
11
+ NAME = module.name(__file__, NAME)
12
+
13
+
14
+ def lock(
15
+ object_name: str,
16
+ lock_name: str = "lock",
17
+ timeout: int = -1,
18
+ verbose: bool = True,
19
+ ) -> bool:
20
+ logger.info(
21
+ "{}.lock: {}.{}{}".format(
22
+ NAME,
23
+ object_name,
24
+ lock_name,
25
+ "" if timeout == -1 else " @ {}".format(string.pretty_duration(timeout)),
26
+ )
27
+ )
28
+
29
+ start_time = time.time()
30
+ while True:
31
+ if timeout > 0 and time.time() - start_time > timeout:
32
+ if verbose:
33
+ logger.warning(
34
+ "{}.lock: {}.{} timeout.".format(
35
+ NAME,
36
+ object_name,
37
+ lock_name,
38
+ )
39
+ )
40
+ return False
41
+
42
+ success, list_of_tags = get_tags(object_name=object_name)
43
+ if not success:
44
+ return False
45
+
46
+ lock_value = list_of_tags.get(lock_name, "")
47
+ if lock_value:
48
+ if verbose:
49
+ logger.warning(
50
+ "{}.lock: {}.{} is locked by {}.".format(
51
+ NAME,
52
+ object_name,
53
+ lock_name,
54
+ lock_value,
55
+ )
56
+ )
57
+ time.sleep(env.MLFLOW_LOCK_WAIT_FOR_CLEARANCE)
58
+ continue
59
+
60
+ lock_value = string.random()
61
+ if not set_tags(
62
+ object_name=object_name,
63
+ tags={lock_name: lock_value},
64
+ log=verbose,
65
+ icon="🔒",
66
+ ):
67
+ return False
68
+
69
+ time.sleep(env.MLFLOW_LOCK_WAIT_FOR_EXCLUSIVITY)
70
+
71
+ success, list_of_tags = get_tags(object_name=object_name)
72
+ if not success:
73
+ return False
74
+
75
+ lock_value_read = list_of_tags.get(lock_name, "")
76
+ if lock_value_read != lock_value:
77
+ if verbose:
78
+ logger.warning(
79
+ "{}.lock: {}.{} is relocked by {} != {}.".format(
80
+ NAME,
81
+ object_name,
82
+ lock_name,
83
+ lock_value_read,
84
+ lock_value,
85
+ )
86
+ )
87
+ time.sleep(env.MLFLOW_LOCK_WAIT_FOR_CLEARANCE)
88
+ continue
89
+
90
+ break
91
+
92
+ logger.info(
93
+ "{}.lock: {}.{} is locked by {}.".format(
94
+ NAME,
95
+ object_name,
96
+ lock_name,
97
+ lock_value,
98
+ )
99
+ )
100
+ return True
101
+
102
+
103
+ def unlock(
104
+ object_name: str,
105
+ lock_name: str = "lock",
106
+ verbose: bool = True,
107
+ ) -> bool:
108
+ logger.info(
109
+ "{}.unlock: {}.{}".format(
110
+ NAME,
111
+ object_name,
112
+ lock_name,
113
+ )
114
+ )
115
+
116
+ return set_tags(
117
+ object_name=object_name,
118
+ tags={lock_name: ""},
119
+ log=verbose,
120
+ icon="🔒",
121
+ )
@@ -16,6 +16,104 @@ from bluer_objects.logger import logger
16
16
  class S3Interface(StorageInterface):
17
17
  name = "s3"
18
18
 
19
+ def clear(
20
+ self,
21
+ do_dryrun: bool = True,
22
+ log: bool = True,
23
+ ) -> bool:
24
+ logger.info(
25
+ "{}.clear({})".format(
26
+ self.__class__.__name__,
27
+ "dryrun" if do_dryrun else "",
28
+ )
29
+ )
30
+
31
+ try:
32
+ s3 = boto3.client(
33
+ "s3",
34
+ endpoint_url=env.S3_STORAGE_ENDPOINT_URL,
35
+ aws_access_key_id=env.S3_STORAGE_AWS_ACCESS_KEY_ID,
36
+ aws_secret_access_key=env.S3_STORAGE_AWS_SECRET_ACCESS_KEY,
37
+ )
38
+
39
+ paginator = s3.get_paginator("list_objects_v2")
40
+ pages = paginator.paginate(
41
+ Bucket=env.S3_STORAGE_BUCKET,
42
+ Prefix="test",
43
+ )
44
+ except Exception as e:
45
+ logger.error(e)
46
+ return False
47
+
48
+ list_of_objects = sorted(
49
+ list(
50
+ set(
51
+ reduce(
52
+ lambda x, y: x + y,
53
+ [
54
+ [
55
+ obj["Key"].split("/", 1)[0]
56
+ for obj in page.get("Contents", [])
57
+ ]
58
+ for page in pages
59
+ ],
60
+ [],
61
+ )
62
+ )
63
+ )
64
+ )
65
+
66
+ logger.info(f"{len(list_of_objects)} object(s) to delete.")
67
+
68
+ for object_name in tqdm(list_of_objects):
69
+ if not self.delete(
70
+ object_name=object_name,
71
+ do_dryrun=do_dryrun,
72
+ ):
73
+ return False
74
+
75
+ return True
76
+
77
+ def delete(
78
+ self,
79
+ object_name: str,
80
+ do_dryrun: bool = True,
81
+ log: bool = True,
82
+ ) -> bool:
83
+ if log:
84
+ logger.info(
85
+ "{}.delete({}){}".format(
86
+ self.__class__.__name__,
87
+ object_name,
88
+ " dryrun" if do_dryrun else "",
89
+ )
90
+ )
91
+ if do_dryrun:
92
+ return True
93
+
94
+ try:
95
+ s3 = boto3.resource(
96
+ "s3",
97
+ endpoint_url=env.S3_STORAGE_ENDPOINT_URL,
98
+ aws_access_key_id=env.S3_STORAGE_AWS_ACCESS_KEY_ID,
99
+ aws_secret_access_key=env.S3_STORAGE_AWS_SECRET_ACCESS_KEY,
100
+ )
101
+ bucket = s3.Bucket(env.S3_STORAGE_BUCKET)
102
+
103
+ objects_to_delete = bucket.objects.filter(Prefix=f"{object_name}/")
104
+ delete_requests = [{"Key": obj.key} for obj in objects_to_delete]
105
+
106
+ if not delete_requests:
107
+ logger.warning(f"no files found under {object_name}.")
108
+ return True
109
+
110
+ bucket.delete_objects(Delete={"Objects": delete_requests})
111
+ except Exception as e:
112
+ logger.error(e)
113
+ return False
114
+
115
+ return True
116
+
19
117
  def download(
20
118
  self,
21
119
  object_name: str,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bluer_objects
3
- Version: 6.166.1
3
+ Version: 6.170.1
4
4
  Summary: 🌀 Object management in Bash.
5
5
  Home-page: https://github.com/kamangir/bluer-objects
6
6
  Author: Arash Abadpour (Kamangir)
@@ -64,6 +64,6 @@ pip install bluer-objects
64
64
 
65
65
  [![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)
66
66
 
67
- built by 🌀 [`bluer README`](https://github.com/kamangir/bluer-objects/tree/main/bluer_objects/README), based on 🌀 [`bluer_objects-6.166.1`](https://github.com/kamangir/bluer-objects).
67
+ built by 🌀 [`bluer README`](https://github.com/kamangir/bluer-objects/tree/main/bluer_objects/README), based on 🌀 [`bluer_objects-6.170.1`](https://github.com/kamangir/bluer-objects).
68
68
 
69
69
  built by 🌀 [`blueness-3.118.1`](https://github.com/kamangir/blueness).
@@ -1,4 +1,4 @@
1
- bluer_objects/__init__.py,sha256=s87Zqxb_mTPssWYNG2qn5n-hBwlNCbjUTyzD0p79oak,315
1
+ bluer_objects/__init__.py,sha256=Up7uiCfpaTfzOTrjFhSTVfEQQ9DtDCzeqOFsRvZ45Gw,315
2
2
  bluer_objects/__main__.py,sha256=Yqfov833_hJuRne19WrGhT5DWAPtdffpoMxeSXS7EGw,359
3
3
  bluer_objects/config.env,sha256=cpmtTuKHIBvVjX30MpAImFgwM0g24qTHwoO-lCJRInA,175
4
4
  bluer_objects/env.py,sha256=aImjtNh8NKaua2rpQVFXWp86QF7nY87fDuMOO14O58E,1956
@@ -115,13 +115,16 @@ bluer_objects/mlflow/objects.py,sha256=aXYHLRCTt1FtDQoyPOG-doCFms7qF6Krz00Fg3kzJ
115
115
  bluer_objects/mlflow/runs.py,sha256=v1IKRvxbuKkengESnG-xdUXxxNSkALMeBmfMQwrUKSs,2416
116
116
  bluer_objects/mlflow/tags.py,sha256=8uBYRrE4weTLrwPqo-c4M21FEVRANf7SGCcxpoCPhuM,2475
117
117
  bluer_objects/mlflow/testing.py,sha256=cJH5Ki02fJN_Xos1j9yvwQChXvMkOa9i12vtDKmkbNc,842
118
+ bluer_objects/mlflow/lock/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
119
+ bluer_objects/mlflow/lock/__main__.py,sha256=xF_xq2UqAsEohSOHjxaFXaw9KopOEDg6LRDM5a4VAPQ,1138
120
+ bluer_objects/mlflow/lock/functions.py,sha256=MOslqblNAOsRvILzLF4q6m2EAwCk4f4zEWQpsy8lVnM,3045
118
121
  bluer_objects/storage/WebDAV.py,sha256=IvYZDST6Cg1rgRhQ5eh3Hrq8V7S3oon9O29MH55QLxA,2922
119
122
  bluer_objects/storage/WebDAVrequest.py,sha256=ihWOxP7h28qj0-5AZ0SsERSBrViq9p4iNVeR4pGBWQo,9836
120
123
  bluer_objects/storage/WebDAVzip.py,sha256=Sd_rU57pJaRa05sKNQiMr85Bg3w7O5k8N1pSN1u8omA,3872
121
124
  bluer_objects/storage/__init__.py,sha256=XosPRjB20wDS-QMwQtr3zqKC9UM7U8z-PHwySGBegcQ,1646
122
125
  bluer_objects/storage/__main__.py,sha256=vZI6rUkrekf1eYUgWOOUnFhl4qPfpByzwb-tihTOiIo,1776
123
126
  bluer_objects/storage/base.py,sha256=72I1zvlpbQbFU20TxqcTodR4m8PYgBPXMfteek8V0_A,1949
124
- bluer_objects/storage/s3.py,sha256=Xm0Dj2qQG8oEJyAM91NV9clDxGJxyN3FQughlFvP17w,5460
127
+ bluer_objects/storage/s3.py,sha256=evUFpPk6PUv1KCXTMq_QCbygqNk0YNAOQr_B4gYrjBE,8342
125
128
  bluer_objects/testing/__init__.py,sha256=DWY5ZtvCnHG_t9BDiqy_ArLOZi-nlyAtPVMLA1PPAMU,62
126
129
  bluer_objects/testing/__main__.py,sha256=hhJV9qn0V_8FxzNDcoHCHr4A7zf9UudnNGJCAPkTBGU,750
127
130
  bluer_objects/testing/functions.py,sha256=AXAfzWLcEPkbSYTehdahshjKJ45C4IJkRs_TgrHOntc,1355
@@ -153,8 +156,8 @@ bluer_objects/tests/test_storage_webdav_request.py,sha256=h2b8PeIx0-hQ2d6PmQcJZy
153
156
  bluer_objects/tests/test_storage_webdav_zip.py,sha256=C19qxhkcHyTwVFzW35vL85SOcXJPkqXXaWUNll0Uyqc,1017
154
157
  bluer_objects/tests/test_testing.py,sha256=d2NH435yqJBl9wmfMqGGd-f0Y0jsL2QhHUXkty9AwPA,235
155
158
  bluer_objects/tests/test_version.py,sha256=Lyf3PMcA22e17BNRk_2VgPrtao6dWEgVoXo68Uds8SE,75
156
- bluer_objects-6.166.1.dist-info/licenses/LICENSE,sha256=ogEPNDSH0_dhiv_lT3ifVIdgIzHAqNA_SemnxUfPBJk,7048
157
- bluer_objects-6.166.1.dist-info/METADATA,sha256=rzbixpQZNpW0GGeFnFo4fr9ZLyQnHFUEW_veSOp3O6w,3678
158
- bluer_objects-6.166.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
159
- bluer_objects-6.166.1.dist-info/top_level.txt,sha256=RX2TpddbnRkurda3G_pAdyeTztP2IhhRPx949GlEvQo,14
160
- bluer_objects-6.166.1.dist-info/RECORD,,
159
+ bluer_objects-6.170.1.dist-info/licenses/LICENSE,sha256=ogEPNDSH0_dhiv_lT3ifVIdgIzHAqNA_SemnxUfPBJk,7048
160
+ bluer_objects-6.170.1.dist-info/METADATA,sha256=ELD0riVQPhS4tFIUH_2uAloiFQl-_KJuL7nc5xozizw,3678
161
+ bluer_objects-6.170.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
162
+ bluer_objects-6.170.1.dist-info/top_level.txt,sha256=RX2TpddbnRkurda3G_pAdyeTztP2IhhRPx949GlEvQo,14
163
+ bluer_objects-6.170.1.dist-info/RECORD,,