ugbio_cloud_utils 1.4.3__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.
- ugbio_cloud_utils/__init__.py +0 -0
- ugbio_cloud_utils/cloud_sync.py +159 -0
- ugbio_cloud_utils-1.4.3.dist-info/METADATA +19 -0
- ugbio_cloud_utils-1.4.3.dist-info/RECORD +7 -0
- ugbio_cloud_utils-1.4.3.dist-info/WHEEL +5 -0
- ugbio_cloud_utils-1.4.3.dist-info/entry_points.txt +3 -0
- ugbio_cloud_utils-1.4.3.dist-info/top_level.txt +1 -0
|
File without changes
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
import boto3
|
|
6
|
+
from google.cloud import storage
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def dir_path(string, *, check_cloud_path=False):
|
|
10
|
+
if os.path.isdir(string):
|
|
11
|
+
return string
|
|
12
|
+
|
|
13
|
+
if check_cloud_path:
|
|
14
|
+
if not string.startswith("gs://") and not string.startswith("s3://"):
|
|
15
|
+
raise ValueError(f"Invalid cloud path {string}\nMust be an s3 or gs path")
|
|
16
|
+
return string
|
|
17
|
+
|
|
18
|
+
raise NotADirectoryError(string)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def download_from_gs(bucket_name, source_blob_name, destination_file_name):
|
|
22
|
+
"""Downloads a blob from the bucket."""
|
|
23
|
+
# bucket_name = "your-bucket-name"
|
|
24
|
+
# source_blob_name = "storage-object-name"
|
|
25
|
+
# destination_file_name = "local/path/to/file"
|
|
26
|
+
|
|
27
|
+
storage_client = storage.Client()
|
|
28
|
+
|
|
29
|
+
bucket = storage_client.bucket(bucket_name)
|
|
30
|
+
blob = bucket.blob(source_blob_name)
|
|
31
|
+
blob.download_to_filename(destination_file_name)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def download_from_s3(bucket_name, object_name, destination_file_name):
|
|
35
|
+
client = boto3.Session(profile_name="default").client("s3")
|
|
36
|
+
client.download_file(bucket_name, object_name, destination_file_name)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def optional_cloud_sync(
|
|
40
|
+
cloud_path_in,
|
|
41
|
+
local_dir_in="/data",
|
|
42
|
+
*,
|
|
43
|
+
print_output=False,
|
|
44
|
+
force_download=False,
|
|
45
|
+
raise_error_is_file_exists=False,
|
|
46
|
+
dry_run=False,
|
|
47
|
+
):
|
|
48
|
+
if cloud_path_in.startswith(("gs://", "s3://")):
|
|
49
|
+
return cloud_sync(
|
|
50
|
+
cloud_path_in, local_dir_in, print_output, force_download, raise_error_is_file_exists, dry_run
|
|
51
|
+
)
|
|
52
|
+
return cloud_path_in
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def cloud_sync( # noqa C901,PLR0912
|
|
56
|
+
cloud_path_in,
|
|
57
|
+
local_dir_in="/data",
|
|
58
|
+
*,
|
|
59
|
+
print_output=False,
|
|
60
|
+
force_download=False,
|
|
61
|
+
raise_error_is_file_exists=False,
|
|
62
|
+
dry_run=False,
|
|
63
|
+
):
|
|
64
|
+
"""Download a file from the cloud to a respective local directory with the same name
|
|
65
|
+
|
|
66
|
+
Parameters
|
|
67
|
+
----------
|
|
68
|
+
cloud_path_in: str
|
|
69
|
+
Path to a file on the cloud (gs / s3), can also be a local file in which case nothing will happen
|
|
70
|
+
local_dir_in: str, optional
|
|
71
|
+
Local directory to which files will be downloaded, under subdirectory "cloud_sync"
|
|
72
|
+
print_output: bool, optional
|
|
73
|
+
Print log messages
|
|
74
|
+
force_download: bool, optional
|
|
75
|
+
If True, download file again even if file with the target name exists (default False)
|
|
76
|
+
raise_error_is_file_exists: bool, optional
|
|
77
|
+
If True and local file already exists, raise ValueError (default False)
|
|
78
|
+
dry_run: bool, optional
|
|
79
|
+
If True, return local path without downloading (default False)
|
|
80
|
+
:raises NotADirectoryError: Not a directory
|
|
81
|
+
:raises FileExistsError: Target local file exists
|
|
82
|
+
:raises NotImplementedError: Unsupported cloud service
|
|
83
|
+
:raises KeyboardInterrupt: Keyboard interrupt
|
|
84
|
+
:returns: a local path to which file was downloaded. If cloud_path_in was an existing local
|
|
85
|
+
file it is returned as is
|
|
86
|
+
-------
|
|
87
|
+
|
|
88
|
+
"""
|
|
89
|
+
if os.path.isfile(cloud_path_in):
|
|
90
|
+
return cloud_path_in
|
|
91
|
+
if not os.path.isdir(local_dir_in):
|
|
92
|
+
raise NotADirectoryError(local_dir_in)
|
|
93
|
+
dir_path(cloud_path_in, check_cloud_path=True)
|
|
94
|
+
cloud_service = cloud_path_in.split(":")[0]
|
|
95
|
+
bucket = cloud_path_in.split("/")[2]
|
|
96
|
+
blob = "/".join(cloud_path_in.split("/")[3:])
|
|
97
|
+
local_path = os.path.join(
|
|
98
|
+
local_dir_in,
|
|
99
|
+
"cloud_sync",
|
|
100
|
+
cloud_service,
|
|
101
|
+
bucket,
|
|
102
|
+
blob,
|
|
103
|
+
)
|
|
104
|
+
if dry_run:
|
|
105
|
+
return local_path
|
|
106
|
+
if not force_download and os.path.isfile(local_path):
|
|
107
|
+
if raise_error_is_file_exists:
|
|
108
|
+
raise FileExistsError(f"target local file {local_path} exists")
|
|
109
|
+
if print_output:
|
|
110
|
+
sys.stdout.write(f"Local file {local_path} already exists, skipping...\n")
|
|
111
|
+
else:
|
|
112
|
+
try:
|
|
113
|
+
if print_output:
|
|
114
|
+
sys.stdout.write(f"Downloading to {local_path}\n")
|
|
115
|
+
os.makedirs(os.path.dirname(local_path), exist_ok=True)
|
|
116
|
+
if cloud_service == "gs":
|
|
117
|
+
download_from_gs(bucket, blob, local_path)
|
|
118
|
+
elif cloud_service == "s3":
|
|
119
|
+
download_from_s3(bucket, blob, local_path)
|
|
120
|
+
else:
|
|
121
|
+
raise NotImplementedError()
|
|
122
|
+
except KeyboardInterrupt:
|
|
123
|
+
if os.path.isfile(local_path):
|
|
124
|
+
sys.stdout.write(f"Keyboard Interrupt - removing incomplete file {local_path}\n")
|
|
125
|
+
os.remove(local_path)
|
|
126
|
+
raise
|
|
127
|
+
|
|
128
|
+
return local_path
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def parse_args(argv):
|
|
132
|
+
parser = argparse.ArgumentParser(description=run.__doc__)
|
|
133
|
+
parser.add_argument("cloud_path", type=str, help="full path to aws s3 / google storage file")
|
|
134
|
+
parser.add_argument(
|
|
135
|
+
"--local_dir",
|
|
136
|
+
type=dir_path,
|
|
137
|
+
default="/data",
|
|
138
|
+
help="local directory the files will sync to",
|
|
139
|
+
)
|
|
140
|
+
args = parser.parse_args(argv[1:])
|
|
141
|
+
return args
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def run(argv: list[str]):
|
|
145
|
+
"""Download aws s3 or google storage file to a respective local path"""
|
|
146
|
+
args = parse_args(argv)
|
|
147
|
+
cloud_path = args.cloud_path
|
|
148
|
+
local_dir = args.local_dir
|
|
149
|
+
if not os.path.isdir(local_dir):
|
|
150
|
+
raise ValueError(f"local_dir {local_dir} does not exist")
|
|
151
|
+
cloud_sync(cloud_path, local_dir, print_output=True)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def main():
|
|
155
|
+
run(sys.argv)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
if __name__ == "__main__":
|
|
159
|
+
run(sys.argv)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: ugbio_cloud_utils
|
|
3
|
+
Version: 1.4.3
|
|
4
|
+
Summary: Ultima Genomics cloud python utils
|
|
5
|
+
Author-email: Avigail Moldovam <avigail.moldovan@ultimagen.com>
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: boto3>=1.35.66
|
|
9
|
+
Requires-Dist: google-cloud-storage>=2.19.0
|
|
10
|
+
|
|
11
|
+
# ugbio_cloud_utils
|
|
12
|
+
|
|
13
|
+
This module includes cloud (AWS/GS) python scripts:
|
|
14
|
+
|
|
15
|
+
List of tools:
|
|
16
|
+
|
|
17
|
+
1. **cloud_sync** - Download aws s3 or google storage file to a respective local path
|
|
18
|
+
|
|
19
|
+
Run `uv run cloud_sync --help` for more details.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
ugbio_cloud_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
ugbio_cloud_utils/cloud_sync.py,sha256=t9n3AJbZNwQiGkaMVGXDpZ1Zx-_kfyhPKFIw_D2X6jA,5192
|
|
3
|
+
ugbio_cloud_utils-1.4.3.dist-info/METADATA,sha256=7zAO81Z_eHCpW16U2xaFmSCrVrF2vCiZxSu6421NR_k,538
|
|
4
|
+
ugbio_cloud_utils-1.4.3.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
5
|
+
ugbio_cloud_utils-1.4.3.dist-info/entry_points.txt,sha256=HEctXBVCAXP9qorkrhKidMG2Rq5aA0O6A_LZmhN6X4g,89
|
|
6
|
+
ugbio_cloud_utils-1.4.3.dist-info/top_level.txt,sha256=RA9O5nTwkzMa9Bvab5CNRKw5WPkgvI4rA6TjFcREny0,18
|
|
7
|
+
ugbio_cloud_utils-1.4.3.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ugbio_cloud_utils
|