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.
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,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (75.6.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ cloud_sync = ugbio_cloud_utils.cloud_sync:main
3
+ run_tests = pytest:main
@@ -0,0 +1 @@
1
+ ugbio_cloud_utils