truefoundry 0.11.10__py3-none-any.whl → 0.11.11__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 truefoundry might be problematic. Click here for more details.
- truefoundry/common/storage_provider_utils.py +35 -10
- truefoundry/ml/artifact/truefoundry_artifact_repo.py +28 -11
- truefoundry/ml/log_types/artifacts/artifact.py +3 -2
- truefoundry/ml/log_types/artifacts/model.py +1 -0
- {truefoundry-0.11.10.dist-info → truefoundry-0.11.11.dist-info}/METADATA +1 -1
- {truefoundry-0.11.10.dist-info → truefoundry-0.11.11.dist-info}/RECORD +8 -8
- {truefoundry-0.11.10.dist-info → truefoundry-0.11.11.dist-info}/WHEEL +0 -0
- {truefoundry-0.11.10.dist-info → truefoundry-0.11.11.dist-info}/entry_points.txt +0 -0
|
@@ -22,6 +22,23 @@ from truefoundry.pydantic_v1 import BaseModel
|
|
|
22
22
|
logger = logging.getLogger("truefoundry")
|
|
23
23
|
|
|
24
24
|
|
|
25
|
+
def truncate_path_for_progress(
|
|
26
|
+
path: str, max_length: int, relpath: bool = False
|
|
27
|
+
) -> str:
|
|
28
|
+
if relpath:
|
|
29
|
+
path = os.path.relpath(path)
|
|
30
|
+
if len(path) <= max_length:
|
|
31
|
+
return path
|
|
32
|
+
parts = path.split(os.sep)
|
|
33
|
+
result = parts[-1] # start with filename
|
|
34
|
+
i = len(parts) - 2
|
|
35
|
+
# keep prepending directories until adding more would exceed max_len - 3
|
|
36
|
+
while i >= 0 and len(result) + len(parts[i]) + 1 <= max_length - 3:
|
|
37
|
+
result = parts[i] + os.sep + result
|
|
38
|
+
i -= 1
|
|
39
|
+
return "..." + os.sep + result
|
|
40
|
+
|
|
41
|
+
|
|
25
42
|
class MultiPartUploadStorageProvider(str, Enum):
|
|
26
43
|
S3_COMPATIBLE = "S3_COMPATIBLE"
|
|
27
44
|
AZURE_BLOB = "AZURE_BLOB"
|
|
@@ -182,7 +199,7 @@ def _file_part_upload(
|
|
|
182
199
|
return response
|
|
183
200
|
|
|
184
201
|
|
|
185
|
-
def s3_compatible_multipart_upload(
|
|
202
|
+
def s3_compatible_multipart_upload( # noqa: C901
|
|
186
203
|
multipart_upload: MultiPartUpload,
|
|
187
204
|
local_file: str,
|
|
188
205
|
multipart_info: _FileMultiPartInfo,
|
|
@@ -190,13 +207,15 @@ def s3_compatible_multipart_upload(
|
|
|
190
207
|
progress_bar: Optional[Progress] = None,
|
|
191
208
|
abort_event: Optional[Event] = None,
|
|
192
209
|
exception_class=HttpRequestException,
|
|
193
|
-
):
|
|
210
|
+
) -> None:
|
|
194
211
|
abort_event = abort_event or Event()
|
|
195
212
|
parts = []
|
|
196
213
|
|
|
197
|
-
if progress_bar:
|
|
214
|
+
if progress_bar is not None:
|
|
198
215
|
multi_part_upload_progress = progress_bar.add_task(
|
|
199
|
-
f"[green]
|
|
216
|
+
f"[green]⬆ {truncate_path_for_progress(local_file, 64, relpath=True)}",
|
|
217
|
+
start=True,
|
|
218
|
+
visible=True,
|
|
200
219
|
)
|
|
201
220
|
|
|
202
221
|
def upload(part_number: int, seek: int) -> None:
|
|
@@ -221,7 +240,7 @@ def s3_compatible_multipart_upload(
|
|
|
221
240
|
multipart_info.num_parts,
|
|
222
241
|
local_file,
|
|
223
242
|
)
|
|
224
|
-
if progress_bar:
|
|
243
|
+
if progress_bar is not None:
|
|
225
244
|
progress_bar.update(
|
|
226
245
|
multi_part_upload_progress,
|
|
227
246
|
advance=multipart_info.part_size,
|
|
@@ -254,10 +273,12 @@ def s3_compatible_multipart_upload(
|
|
|
254
273
|
timeout=2 * 60,
|
|
255
274
|
)
|
|
256
275
|
response.raise_for_status()
|
|
276
|
+
if progress_bar is not None:
|
|
277
|
+
progress_bar.refresh()
|
|
257
278
|
logger.debug("Multipart upload of %s completed", local_file)
|
|
258
279
|
|
|
259
280
|
|
|
260
|
-
def azure_multi_part_upload(
|
|
281
|
+
def azure_multi_part_upload( # noqa: C901
|
|
261
282
|
multipart_upload: MultiPartUpload,
|
|
262
283
|
local_file: str,
|
|
263
284
|
multipart_info: _FileMultiPartInfo,
|
|
@@ -265,12 +286,14 @@ def azure_multi_part_upload(
|
|
|
265
286
|
progress_bar: Optional[Progress] = None,
|
|
266
287
|
abort_event: Optional[Event] = None,
|
|
267
288
|
exception_class=HttpRequestException,
|
|
268
|
-
):
|
|
289
|
+
) -> None:
|
|
269
290
|
abort_event = abort_event or Event()
|
|
270
291
|
|
|
271
|
-
if progress_bar:
|
|
292
|
+
if progress_bar is not None:
|
|
272
293
|
multi_part_upload_progress = progress_bar.add_task(
|
|
273
|
-
f"[green]
|
|
294
|
+
f"[green]⬆ {truncate_path_for_progress(local_file, 64, relpath=True)}",
|
|
295
|
+
start=True,
|
|
296
|
+
visible=True,
|
|
274
297
|
)
|
|
275
298
|
|
|
276
299
|
def upload(part_number: int, seek: int):
|
|
@@ -289,7 +312,7 @@ def azure_multi_part_upload(
|
|
|
289
312
|
abort_event=abort_event,
|
|
290
313
|
exception_class=exception_class,
|
|
291
314
|
)
|
|
292
|
-
if progress_bar:
|
|
315
|
+
if progress_bar is not None:
|
|
293
316
|
progress_bar.update(
|
|
294
317
|
multi_part_upload_progress,
|
|
295
318
|
advance=multipart_info.part_size,
|
|
@@ -328,4 +351,6 @@ def azure_multi_part_upload(
|
|
|
328
351
|
timeout=2 * 60,
|
|
329
352
|
)
|
|
330
353
|
response.raise_for_status()
|
|
354
|
+
if progress_bar is not None:
|
|
355
|
+
progress_bar.refresh()
|
|
331
356
|
logger.debug("Multipart upload of %s completed", local_file)
|
|
@@ -40,6 +40,7 @@ from truefoundry.common.storage_provider_utils import (
|
|
|
40
40
|
azure_multi_part_upload,
|
|
41
41
|
decide_file_parts,
|
|
42
42
|
s3_compatible_multipart_upload,
|
|
43
|
+
truncate_path_for_progress,
|
|
43
44
|
)
|
|
44
45
|
from truefoundry.ml._autogen.client import ( # type: ignore[attr-defined]
|
|
45
46
|
ApiClient,
|
|
@@ -125,14 +126,14 @@ def _signed_url_upload_file(
|
|
|
125
126
|
augmented_raise_for_status(response, exception_class=MlFoundryException) # type: ignore
|
|
126
127
|
return
|
|
127
128
|
|
|
128
|
-
|
|
129
|
-
f"[green]
|
|
129
|
+
task_id = progress_bar.add_task(
|
|
130
|
+
f"[green]⬆ {truncate_path_for_progress(local_file, 64, relpath=True)}",
|
|
131
|
+
start=True,
|
|
132
|
+
visible=True,
|
|
130
133
|
)
|
|
131
134
|
|
|
132
135
|
def callback(length):
|
|
133
|
-
progress_bar.update(
|
|
134
|
-
task_progress_bar, advance=length, total=os.stat(local_file).st_size
|
|
135
|
-
)
|
|
136
|
+
progress_bar.update(task_id, advance=length, total=os.stat(local_file).st_size)
|
|
136
137
|
if abort_event and abort_event.is_set():
|
|
137
138
|
raise Exception("aborting upload")
|
|
138
139
|
|
|
@@ -147,6 +148,9 @@ def _signed_url_upload_file(
|
|
|
147
148
|
) as response:
|
|
148
149
|
augmented_raise_for_status(response, exception_class=MlFoundryException) # type: ignore
|
|
149
150
|
|
|
151
|
+
if progress_bar is not None:
|
|
152
|
+
progress_bar.refresh()
|
|
153
|
+
|
|
150
154
|
|
|
151
155
|
def _download_file_using_http_uri(
|
|
152
156
|
http_uri,
|
|
@@ -167,11 +171,18 @@ def _download_file_using_http_uri(
|
|
|
167
171
|
exception_class=MlFoundryException, # type: ignore
|
|
168
172
|
) as response:
|
|
169
173
|
augmented_raise_for_status(response, exception_class=MlFoundryException) # type: ignore
|
|
170
|
-
file_size = int(response.headers.get("Content-Length",
|
|
174
|
+
file_size = int(response.headers.get("Content-Length", -1))
|
|
175
|
+
if file_size == 0 and callback:
|
|
176
|
+
# special case for empty files
|
|
177
|
+
callback(1, 1)
|
|
178
|
+
file_size = file_size if file_size > 0 else 0
|
|
171
179
|
with open(download_path, "wb") as output_file:
|
|
172
180
|
for chunk in response.iter_content(chunk_size=chunk_size):
|
|
173
181
|
if callback:
|
|
174
182
|
callback(len(chunk), file_size)
|
|
183
|
+
print(
|
|
184
|
+
f"Sent callback for {download_path} {len(chunk)} / {file_size}"
|
|
185
|
+
)
|
|
175
186
|
if not chunk:
|
|
176
187
|
break
|
|
177
188
|
output_file.write(chunk)
|
|
@@ -658,15 +669,18 @@ class MlFoundryArtifactsRepository:
|
|
|
658
669
|
logger.info("Downloading %s to %s", remote_file_path, local_path)
|
|
659
670
|
|
|
660
671
|
if progress_bar is not None:
|
|
661
|
-
|
|
662
|
-
f"[green]
|
|
672
|
+
task_id = progress_bar.add_task(
|
|
673
|
+
f"[green]⬇ {truncate_path_for_progress(remote_file_path, 64)}",
|
|
674
|
+
start=True,
|
|
675
|
+
visible=True,
|
|
663
676
|
)
|
|
664
677
|
|
|
665
|
-
def callback(
|
|
678
|
+
def callback(chunk_size: int, total_file_size: int):
|
|
679
|
+
nonlocal task_id
|
|
666
680
|
if progress_bar is not None:
|
|
667
681
|
progress_bar.update(
|
|
668
|
-
|
|
669
|
-
advance=
|
|
682
|
+
task_id,
|
|
683
|
+
advance=chunk_size,
|
|
670
684
|
total=total_file_size,
|
|
671
685
|
)
|
|
672
686
|
if abort_event and abort_event.is_set():
|
|
@@ -677,6 +691,9 @@ class MlFoundryArtifactsRepository:
|
|
|
677
691
|
download_path=local_path,
|
|
678
692
|
callback=callback,
|
|
679
693
|
)
|
|
694
|
+
|
|
695
|
+
if progress_bar is not None:
|
|
696
|
+
progress_bar.refresh()
|
|
680
697
|
logger.debug("Downloaded %s to %s", remote_file_path, local_path)
|
|
681
698
|
|
|
682
699
|
def _download_artifact(
|
|
@@ -347,10 +347,11 @@ class ArtifactVersion:
|
|
|
347
347
|
artifact_version.download(path="<your-desired-download-path>")
|
|
348
348
|
```
|
|
349
349
|
"""
|
|
350
|
-
|
|
350
|
+
download_info = self._download(
|
|
351
351
|
path=path, overwrite=overwrite, progress=progress
|
|
352
352
|
)
|
|
353
|
-
|
|
353
|
+
logger.info("Downloaded artifact contents to %s", download_info.download_dir)
|
|
354
|
+
return download_info.download_dir
|
|
354
355
|
|
|
355
356
|
def delete(self) -> bool:
|
|
356
357
|
"""
|
|
@@ -48,7 +48,7 @@ truefoundry/common/exceptions.py,sha256=jkU0N7hV_P-EhXeud4I5vuB9glXXZSWPf8LcH04m
|
|
|
48
48
|
truefoundry/common/request_utils.py,sha256=e9qrAQ1MutU7JALDKcucmNd0KQEVBqgW3yx0w1zeHIU,5700
|
|
49
49
|
truefoundry/common/servicefoundry_client.py,sha256=2fYhdVPSvLXz5C5tosOq86JD8WM3IRUIy1VO9deDxZI,3340
|
|
50
50
|
truefoundry/common/session.py,sha256=d9l3TEBpqVP4mr4mTGY1qVxc815skzMlNNdw14otg34,2923
|
|
51
|
-
truefoundry/common/storage_provider_utils.py,sha256=
|
|
51
|
+
truefoundry/common/storage_provider_utils.py,sha256=jX9maCtWusZx63324cmPxHiGeIluZZzbDaJ1QYTIhAw,11856
|
|
52
52
|
truefoundry/common/types.py,sha256=BMJFCsR1lPJAw66IQBSvLyV4I6o_x5oj78gVsUa9si8,188
|
|
53
53
|
truefoundry/common/utils.py,sha256=P0FuAadoJGdpieUORLSN-PiFnkyoGO-K2cS4OPITBWg,6714
|
|
54
54
|
truefoundry/common/warnings.py,sha256=xDMhR_-ZGC40Ycaj6nlFb5MYPexn8WbKCHd4FlflTXQ,705
|
|
@@ -349,7 +349,7 @@ truefoundry/ml/_autogen/models/schema.py,sha256=a_bp42MMPUbwO3407m0UW2W8EOhnxZXf
|
|
|
349
349
|
truefoundry/ml/_autogen/models/signature.py,sha256=rBjpxUIsEeWM0sIyYG5uCJB18DKHR4k5yZw8TzuoP48,4987
|
|
350
350
|
truefoundry/ml/_autogen/models/utils.py,sha256=c7RtSLXhOLcP8rjuUtfnMdaKVTZvvbsmw98gPAkAFrs,24371
|
|
351
351
|
truefoundry/ml/artifact/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
352
|
-
truefoundry/ml/artifact/truefoundry_artifact_repo.py,sha256=
|
|
352
|
+
truefoundry/ml/artifact/truefoundry_artifact_repo.py,sha256=ITZbhvzwa8NbN66K7V9iufzZHVguuLYn1pHCDSE-P-o,36273
|
|
353
353
|
truefoundry/ml/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
354
354
|
truefoundry/ml/cli/cli.py,sha256=MwpY7z_NEeJE_XIP7XbZELjNeu2vpMmohttHCKDRk54,335
|
|
355
355
|
truefoundry/ml/cli/utils.py,sha256=j6_mZ4Spn114mz3P4QQ8jx0tmorXIuyQnHXVUSDvZi4,1035
|
|
@@ -365,11 +365,11 @@ truefoundry/ml/log_types/plot.py,sha256=LDh4uy6z2P_a2oPM2lc85c0lt8utVvunohzeMawF
|
|
|
365
365
|
truefoundry/ml/log_types/pydantic_base.py,sha256=eBlw_AEyAz4iJKDP4zgJOCFWcldwQqpf7FADW1jzIQY,272
|
|
366
366
|
truefoundry/ml/log_types/utils.py,sha256=xjJ21jdPScvFmw3TbVh5NCzbzJwaqiXJyiiT4xxX1EI,335
|
|
367
367
|
truefoundry/ml/log_types/artifacts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
368
|
-
truefoundry/ml/log_types/artifacts/artifact.py,sha256=
|
|
368
|
+
truefoundry/ml/log_types/artifacts/artifact.py,sha256=OXJDaJZLGE8jA-6A8pdApfpbz1x3O-8rIMWUkG_8hYA,19940
|
|
369
369
|
truefoundry/ml/log_types/artifacts/constants.py,sha256=7blG13UXSkZVZkN8EDFqaH-a_ZonJA6pI0gwJwkIZ-s,1298
|
|
370
370
|
truefoundry/ml/log_types/artifacts/dataset.py,sha256=OgWIoT59AhMw8P01FfvUKbJ3EL6HQf_Xw8X4E3Ff5Sg,13172
|
|
371
371
|
truefoundry/ml/log_types/artifacts/general_artifact.py,sha256=yr-SQ2fhUR_sE1MB5zoHHYpGC8tizH_-t3lhsxCAULU,2747
|
|
372
|
-
truefoundry/ml/log_types/artifacts/model.py,sha256=
|
|
372
|
+
truefoundry/ml/log_types/artifacts/model.py,sha256=j4Gf0TKpi-JCOBqCdkH40pkpDLwvSk04KgQn2sK5fZI,24911
|
|
373
373
|
truefoundry/ml/log_types/artifacts/utils.py,sha256=INZhhzl6OaD6qFAyxaLJAhXhFd6wKNujMj-lq2v8p4Q,9340
|
|
374
374
|
truefoundry/ml/log_types/image/__init__.py,sha256=fcOq8yQnNj1rkLcPeIjLXBpdA1WIeiPsXOlAAvMxx7M,76
|
|
375
375
|
truefoundry/ml/log_types/image/constants.py,sha256=wLtGEOA4T5fZHSlOXPuNDLX3lpbCtwlvGKPFk_1fah0,255
|
|
@@ -387,7 +387,7 @@ truefoundry/workflow/remote_filesystem/__init__.py,sha256=LQ95ViEjJ7Ts4JcCGOxMPs
|
|
|
387
387
|
truefoundry/workflow/remote_filesystem/logger.py,sha256=em2l7D6sw7xTLDP0kQSLpgfRRCLpN14Qw85TN7ujQcE,1022
|
|
388
388
|
truefoundry/workflow/remote_filesystem/tfy_signed_url_client.py,sha256=xcT0wQmQlgzcj0nP3tJopyFSVWT1uv3nhiTIuwfXYeg,12342
|
|
389
389
|
truefoundry/workflow/remote_filesystem/tfy_signed_url_fs.py,sha256=nSGPZu0Gyd_jz0KsEE-7w_BmnTD8CVF1S8cUJoxaCbc,13305
|
|
390
|
-
truefoundry-0.11.
|
|
391
|
-
truefoundry-0.11.
|
|
392
|
-
truefoundry-0.11.
|
|
393
|
-
truefoundry-0.11.
|
|
390
|
+
truefoundry-0.11.11.dist-info/METADATA,sha256=KvW4uvzJ44zwy8dOpOK_NfMp3IS2h3Z44gG5OOowTHI,2761
|
|
391
|
+
truefoundry-0.11.11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
392
|
+
truefoundry-0.11.11.dist-info/entry_points.txt,sha256=xVjn7RMN-MW2-9f7YU-bBdlZSvvrwzhpX1zmmRmsNPU,98
|
|
393
|
+
truefoundry-0.11.11.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|