truefoundry 0.4.0rc2__py3-none-any.whl → 0.4.0rc4__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.

Files changed (82) hide show
  1. truefoundry/__init__.py +2 -0
  2. truefoundry/autodeploy/agents/developer.py +1 -1
  3. truefoundry/autodeploy/agents/project_identifier.py +2 -2
  4. truefoundry/autodeploy/agents/tester.py +1 -1
  5. truefoundry/autodeploy/cli.py +1 -1
  6. truefoundry/autodeploy/tools/list_files.py +1 -1
  7. truefoundry/{deploy/lib/auth → common}/auth_service_client.py +50 -40
  8. truefoundry/common/constants.py +12 -0
  9. truefoundry/{deploy/lib/auth → common}/credential_file_manager.py +7 -7
  10. truefoundry/{deploy/lib/auth → common}/credential_provider.py +9 -12
  11. truefoundry/{ml/services → common}/entities.py +59 -43
  12. truefoundry/common/exceptions.py +12 -0
  13. truefoundry/common/request_utils.py +36 -8
  14. truefoundry/common/servicefoundry_client.py +91 -0
  15. truefoundry/common/utils.py +56 -0
  16. truefoundry/deploy/auto_gen/models.py +4 -6
  17. truefoundry/deploy/cli/cli.py +2 -0
  18. truefoundry/deploy/cli/commands/apply_command.py +1 -1
  19. truefoundry/deploy/cli/commands/build_command.py +1 -1
  20. truefoundry/deploy/cli/commands/deploy_command.py +1 -1
  21. truefoundry/deploy/cli/commands/login_command.py +2 -2
  22. truefoundry/deploy/cli/commands/patch_application_command.py +1 -1
  23. truefoundry/deploy/cli/commands/patch_command.py +1 -1
  24. truefoundry/deploy/cli/commands/terminate_comand.py +1 -1
  25. truefoundry/deploy/cli/util.py +1 -1
  26. truefoundry/deploy/function_service/remote/remote.py +1 -1
  27. truefoundry/deploy/lib/auth/servicefoundry_session.py +2 -2
  28. truefoundry/deploy/lib/clients/servicefoundry_client.py +120 -150
  29. truefoundry/deploy/lib/const.py +1 -35
  30. truefoundry/deploy/lib/exceptions.py +0 -11
  31. truefoundry/deploy/lib/model/entity.py +1 -112
  32. truefoundry/deploy/lib/session.py +13 -26
  33. truefoundry/deploy/lib/util.py +0 -37
  34. truefoundry/deploy/python_deploy_codegen.py +2 -2
  35. truefoundry/deploy/v2/lib/deploy.py +3 -3
  36. truefoundry/ml/__init__.py +0 -2
  37. truefoundry/ml/artifact/truefoundry_artifact_repo.py +63 -22
  38. truefoundry/ml/autogen/client/__init__.py +0 -3
  39. truefoundry/ml/autogen/client/api/experiments_api.py +0 -165
  40. truefoundry/ml/autogen/client/models/__init__.py +0 -3
  41. truefoundry/ml/autogen/client/models/artifact_dto.py +6 -6
  42. truefoundry/ml/autogen/client/models/artifact_version_dto.py +8 -8
  43. truefoundry/ml/autogen/client/models/create_artifact_response_dto.py +2 -3
  44. truefoundry/ml/autogen/client/models/create_artifact_version_response_dto.py +2 -3
  45. truefoundry/ml/autogen/client/models/create_python_deployment_config_request_dto.py +2 -2
  46. truefoundry/ml/autogen/client/models/create_python_deployment_config_response_dto.py +2 -3
  47. truefoundry/ml/autogen/client/models/create_run_request_dto.py +5 -5
  48. truefoundry/ml/autogen/client/models/create_run_response_dto.py +2 -3
  49. truefoundry/ml/autogen/client/models/dataset_dto.py +10 -10
  50. truefoundry/ml/autogen/client/models/experiment_dto.py +18 -18
  51. truefoundry/ml/autogen/client/models/get_latest_run_log_response_dto.py +2 -3
  52. truefoundry/ml/autogen/client/models/get_tenant_id_response_dto.py +4 -5
  53. truefoundry/ml/autogen/client/models/model_dto.py +6 -6
  54. truefoundry/ml/autogen/client/models/model_version_dto.py +15 -8
  55. truefoundry/ml/autogen/client/models/run_info_dto.py +10 -10
  56. truefoundry/ml/autogen/client/models/update_run_response_dto.py +2 -3
  57. truefoundry/ml/autogen/client_README.md +0 -2
  58. truefoundry/ml/clients/entities.py +8 -0
  59. truefoundry/ml/{services/servicefoundry_service.py → clients/servicefoundry_client.py} +20 -10
  60. truefoundry/ml/{services → clients}/utils.py +2 -2
  61. truefoundry/ml/env_vars.py +1 -5
  62. truefoundry/ml/internal_namespace.py +8 -8
  63. truefoundry/ml/log_types/artifacts/artifact.py +7 -3
  64. truefoundry/ml/log_types/artifacts/dataset.py +1 -1
  65. truefoundry/ml/log_types/artifacts/model.py +7 -8
  66. truefoundry/ml/log_types/image/image.py +7 -8
  67. truefoundry/ml/log_types/image/image_normalizer.py +7 -6
  68. truefoundry/ml/mlfoundry_api.py +5 -17
  69. truefoundry/ml/mlfoundry_run.py +0 -5
  70. truefoundry/ml/run_utils.py +1 -10
  71. truefoundry/ml/session.py +14 -117
  72. truefoundry/pydantic_v1.py +1 -1
  73. truefoundry/workflow/__init__.py +16 -1
  74. {truefoundry-0.4.0rc2.dist-info → truefoundry-0.4.0rc4.dist-info}/METADATA +2 -2
  75. {truefoundry-0.4.0rc2.dist-info → truefoundry-0.4.0rc4.dist-info}/RECORD +78 -77
  76. truefoundry/deploy/lib/clients/utils.py +0 -41
  77. truefoundry/ml/autogen/client/models/backfill_default_storage_integration_id_request_dto.py +0 -67
  78. truefoundry/ml/login.py +0 -241
  79. truefoundry/ml/services/auth_service.py +0 -109
  80. /truefoundry/ml/{services → clients}/__init__.py +0 -0
  81. {truefoundry-0.4.0rc2.dist-info → truefoundry-0.4.0rc4.dist-info}/WHEEL +0 -0
  82. {truefoundry-0.4.0rc2.dist-info → truefoundry-0.4.0rc4.dist-info}/entry_points.txt +0 -0
@@ -1,14 +1,11 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import datetime
4
- import time
5
4
  from enum import Enum
6
5
  from typing import Any, Dict, List, Optional, Union
7
6
 
8
- import jwt
9
-
10
7
  from truefoundry.deploy.lib.util import get_application_fqn_from_deployment_fqn
11
- from truefoundry.pydantic_v1 import BaseModel, Extra, Field, constr, validator
8
+ from truefoundry.pydantic_v1 import BaseModel, Extra, Field
12
9
 
13
10
  # TODO: switch to Enums for str literals
14
11
  # TODO: Need a better approach to keep fields in sync with server
@@ -215,114 +212,6 @@ class Application(Entity):
215
212
  }
216
213
 
217
214
 
218
- class UserType(Enum):
219
- user = "user"
220
- serviceaccount = "serviceaccount"
221
-
222
-
223
- class UserInfo(BaseModel):
224
- user_id: constr(min_length=1)
225
- user_type: UserType = UserType.user
226
- email: Optional[str] = None
227
- tenant_name: constr(min_length=1) = Field(alias="tenantName")
228
-
229
- class Config:
230
- allow_population_by_field_name = True
231
- allow_mutation = False
232
-
233
-
234
- class TenantInfo(BaseModel):
235
- tenant_name: constr(min_length=1) = Field(alias="tenantName")
236
- auth_server_url: str
237
-
238
- class Config:
239
- allow_population_by_field_name = True
240
- allow_mutation = False
241
-
242
-
243
- class Token(BaseModel):
244
- access_token: constr(min_length=1) = Field(alias="accessToken", repr=False)
245
- refresh_token: Optional[constr(min_length=1)] = Field(
246
- alias="refreshToken", repr=False
247
- )
248
- decoded_value: Optional[Dict] = Field(exclude=True, repr=False)
249
-
250
- class Config:
251
- allow_population_by_field_name = True
252
- allow_mutation = False
253
-
254
- @validator("decoded_value", always=True, pre=True)
255
- def _decode_jwt(cls, v, values, **kwargs):
256
- access_token = values["access_token"]
257
- return jwt.decode(
258
- access_token,
259
- options={
260
- "verify_signature": False,
261
- "verify_aud": False,
262
- "verify_exp": False,
263
- },
264
- )
265
-
266
- @property
267
- def tenant_name(self) -> str:
268
- return self.decoded_value["tenantName"]
269
-
270
- def is_going_to_be_expired(self, buffer_in_seconds: int = 120) -> bool:
271
- exp = int(self.decoded_value["exp"])
272
- return (exp - time.time()) < buffer_in_seconds
273
-
274
- def to_user_info(self) -> UserInfo:
275
- return UserInfo(
276
- user_id=self.decoded_value["username"],
277
- email=self.decoded_value["email"]
278
- if "email" in self.decoded_value
279
- else None,
280
- user_type=UserType(self.decoded_value.get("userType", UserType.user.value)),
281
- tenant_name=self.tenant_name,
282
- )
283
-
284
-
285
- class CredentialsFileContent(BaseModel):
286
- access_token: constr(min_length=1) = Field(repr=False)
287
- refresh_token: Optional[constr(min_length=1)] = Field(repr=False)
288
- host: constr(min_length=1)
289
-
290
- class Config:
291
- allow_mutation = False
292
-
293
- def to_token(self) -> Token:
294
- return Token(access_token=self.access_token, refresh_token=self.refresh_token)
295
-
296
-
297
- class DeviceCode(BaseModel):
298
- user_code: str = Field(alias="userCode")
299
- device_code: str = Field(alias="deviceCode")
300
- verification_url: Optional[str] = Field(alias="verificationURI")
301
- complete_verification_url: Optional[str] = Field(alias="verificationURIComplete")
302
- expires_in_seconds: int = Field(alias="expiresInSeconds", default=60)
303
- interval_in_seconds: int = Field(alias="intervalInSeconds", default=1)
304
- message: Optional[str] = Field(alias="message")
305
-
306
- class Config:
307
- allow_population_by_field_name = True
308
- allow_mutation = False
309
-
310
- def get_user_clickable_url(self, auth_host: str) -> str:
311
- return f"{auth_host}/authorize/device?userCode={self.user_code}"
312
-
313
-
314
- class PythonSDKConfig(BaseModel):
315
- min_version: str = Field(alias="minVersion")
316
- truefoundry_cli_min_version: str = Field(alias="truefoundryCliMinVersion")
317
- use_sfy_server_auth_apis: Optional[bool] = Field(
318
- alias="useSFYServerAuthAPIs", default=False
319
- )
320
-
321
- class Config:
322
- allow_population_by_field_name = True
323
- allow_mutation = False
324
-
325
-
326
215
  class JobRun(Base):
327
216
  name: str
328
217
  applicationName: str
@@ -3,38 +3,22 @@ from typing import Optional
3
3
 
4
4
  import rich_click as click
5
5
 
6
+ from truefoundry.common.auth_service_client import AuthServiceClient
7
+ from truefoundry.common.constants import TFY_API_KEY_ENV_KEY, TFY_HOST_ENV_KEY
8
+ from truefoundry.common.credential_file_manager import CredentialsFileManager
9
+ from truefoundry.common.credential_provider import EnvCredentialProvider
10
+ from truefoundry.common.entities import CredentialsFileContent, Token
11
+ from truefoundry.common.utils import resolve_base_url
6
12
  from truefoundry.deploy.io.output_callback import OutputCallBack
7
- from truefoundry.deploy.lib.auth.auth_service_client import AuthServiceClient
8
- from truefoundry.deploy.lib.auth.credential_file_manager import CredentialsFileManager
9
- from truefoundry.deploy.lib.auth.credential_provider import EnvCredentialProvider
10
- from truefoundry.deploy.lib.clients.utils import resolve_base_url
11
13
  from truefoundry.deploy.lib.const import (
12
- API_KEY_ENV_NAME,
13
- HOST_ENV_NAME,
14
- OLD_SFY_PROFILES_FILEPATH,
15
- OLD_SFY_SESSIONS_FILEPATH,
16
14
  RICH_OUTPUT_CALLBACK,
17
15
  )
18
16
  from truefoundry.deploy.lib.messages import (
19
17
  PROMPT_ALREADY_LOGGED_OUT,
20
18
  PROMPT_LOGOUT_SUCCESSFUL,
21
19
  )
22
- from truefoundry.deploy.lib.model.entity import CredentialsFileContent, Token
23
20
  from truefoundry.logger import logger
24
21
 
25
- if OLD_SFY_PROFILES_FILEPATH.exists():
26
- logger.warning(
27
- "%s file is deprecated. You can delete this file now.",
28
- OLD_SFY_PROFILES_FILEPATH,
29
- )
30
-
31
-
32
- if OLD_SFY_SESSIONS_FILEPATH.exists():
33
- logger.warning(
34
- "%s file is deprecated. You can delete this file now.",
35
- OLD_SFY_SESSIONS_FILEPATH,
36
- )
37
-
38
22
 
39
23
  def login(
40
24
  api_key: Optional[str] = None,
@@ -42,13 +26,13 @@ def login(
42
26
  relogin: bool = False,
43
27
  output_hook: OutputCallBack = RICH_OUTPUT_CALLBACK,
44
28
  ) -> bool:
45
- if API_KEY_ENV_NAME in os.environ and HOST_ENV_NAME in os.environ:
29
+ if TFY_API_KEY_ENV_KEY in os.environ and TFY_HOST_ENV_KEY in os.environ:
46
30
  logger.warning(
47
31
  "Skipping login because environment variables %s and "
48
32
  "%s are set and will be used when running truefoundry. "
49
33
  "If you want to relogin then unset these environment keys.",
50
- HOST_ENV_NAME,
51
- API_KEY_ENV_NAME,
34
+ TFY_HOST_ENV_KEY,
35
+ TFY_API_KEY_ENV_KEY,
52
36
  )
53
37
  return False
54
38
 
@@ -129,7 +113,10 @@ def _login_with_device_code(
129
113
  if device_code.message:
130
114
  message = device_code.message
131
115
  else:
132
- message = f"Please open the following URL in a browser and enter the code {device_code.user_code} when prompted: {device_code.verification_url}"
116
+ message = (
117
+ f"Please open the following URL in a browser and enter the code {device_code.user_code} "
118
+ f"when prompted: {device_code.verification_url}"
119
+ )
133
120
  else:
134
121
  auto_open_url = device_code.get_user_clickable_url(auth_host=base_url)
135
122
  if auto_open_url:
@@ -1,7 +1,5 @@
1
1
  import os
2
2
  import re
3
- from functools import lru_cache, wraps
4
- from time import monotonic_ns
5
3
  from typing import Union
6
4
 
7
5
  from truefoundry.deploy.lib.const import (
@@ -41,23 +39,6 @@ def get_deployment_fqn_from_application_fqn(
41
39
  return f"{application_fqn}:{version}"
42
40
 
43
41
 
44
- def is_notebook():
45
- # https://stackoverflow.com/questions/15411967/how-can-i-check-if-code-is-executed-in-the-ipython-notebook
46
- try:
47
- # noinspection PyUnresolvedReferences
48
- shell = get_ipython().__class__
49
- if shell.__name__ == "ZMQInteractiveShell":
50
- return True # Jupyter notebook or qtconsole
51
- elif shell.__name__ == "TerminalInteractiveShell":
52
- return False # Terminal running IPython
53
- elif "google.colab" in str(shell):
54
- return True # google colab notebook
55
- else:
56
- return False # Other type (?)
57
- except NameError:
58
- return False # Probably standard Python interpreter
59
-
60
-
61
42
  def find_list_paths(data, parent_key="", sep="."):
62
43
  list_paths = []
63
44
  if isinstance(data, dict):
@@ -70,21 +51,3 @@ def find_list_paths(data, parent_key="", sep="."):
70
51
  new_key = f"{parent_key}[{i}]"
71
52
  list_paths.extend(find_list_paths(value, new_key, sep))
72
53
  return list_paths
73
-
74
-
75
- def timed_lru_cache(seconds: int = 300, maxsize: int = None):
76
- def wrapper_cache(func):
77
- func = lru_cache(maxsize=maxsize)(func)
78
- func.delta = seconds * 10**9
79
- func.expiration = monotonic_ns() + func.delta
80
-
81
- @wraps(func)
82
- def wrapped_func(*args, **kwargs):
83
- if monotonic_ns() >= func.expiration:
84
- func.cache_clear()
85
- func.expiration = monotonic_ns() + func.delta
86
- return func(*args, **kwargs)
87
-
88
- return wrapped_func
89
-
90
- return wrapper_cache
@@ -101,11 +101,11 @@ def add_local_source_comment(code):
101
101
  return "\n".join(new_lines)
102
102
 
103
103
 
104
- def convert_deployment_config_to_python(workspace_fqn: str, deployment_config: dict):
104
+ def convert_deployment_config_to_python(workspace_fqn: str, application_spec: dict):
105
105
  """
106
106
  Convert a deployment config to a python file that can be used to deploy to a workspace
107
107
  """
108
- application = Application.parse_obj(deployment_config)
108
+ application = Application.parse_obj(application_spec)
109
109
  application_type = application.__root__.type
110
110
 
111
111
  spec_repr = get_python_repr(application.__root__)
@@ -4,12 +4,12 @@ from typing import List, Optional, TypeVar
4
4
 
5
5
  from rich.status import Status
6
6
 
7
+ from truefoundry.common.utils import poll_for_function
7
8
  from truefoundry.deploy.auto_gen import models as auto_gen_models
8
9
  from truefoundry.deploy.builder.docker_service import env_has_docker
9
10
  from truefoundry.deploy.lib.clients.servicefoundry_client import (
10
11
  ServiceFoundryServiceClient,
11
12
  )
12
- from truefoundry.deploy.lib.clients.utils import poll_for_function
13
13
  from truefoundry.deploy.lib.dao.workspace import get_workspace_by_fqn
14
14
  from truefoundry.deploy.lib.model.entity import Deployment, DeploymentTransitionStatus
15
15
  from truefoundry.deploy.lib.util import get_application_fqn_from_deployment_fqn
@@ -45,7 +45,7 @@ def _handle_if_local_source(component: Component, workspace_fqn: str) -> Compone
45
45
  local_build = False
46
46
  else:
47
47
  logger.info(
48
- "Found locally installed docker, image will be built locally and then pushed. "
48
+ "Found locally installed docker, image will be built locally and then pushed.\n"
49
49
  "If you want to always build remotely instead of locally, "
50
50
  "please set `image.build_source.local_build` to `false` in your YAML spec or equivalently set "
51
51
  "`image=Build(build_source=LocalSource(local_build=False, ...))` in your "
@@ -72,7 +72,7 @@ def _handle_if_local_source(component: Component, workspace_fqn: str) -> Compone
72
72
  component_name=component.name,
73
73
  )
74
74
  else:
75
- # We'll build image on Truefoundry servers, upload the source and update image.build_source
75
+ # We'll build image on TrueFoundry servers, upload the source and update image.build_source
76
76
  logger.info("Uploading code for %s '%s'", component.type, component.name)
77
77
  new_component.image.build_source = local_source_to_remote_source(
78
78
  local_source=component.image.build_source,
@@ -13,7 +13,6 @@ from truefoundry.ml.log_types.artifacts.model import (
13
13
  ModelVersion,
14
14
  )
15
15
  from truefoundry.ml.logger import init_logger
16
- from truefoundry.ml.login import login
17
16
  from truefoundry.ml.mlfoundry_api import get_client
18
17
  from truefoundry.ml.mlfoundry_run import MlFoundryRun
19
18
 
@@ -33,7 +32,6 @@ __all__ = [
33
32
  "Plot",
34
33
  "ViewType",
35
34
  "get_client",
36
- "login",
37
35
  ]
38
36
 
39
37
  init_logger()
@@ -23,6 +23,7 @@ from urllib.parse import unquote
23
23
  from urllib.request import pathname2url
24
24
 
25
25
  import requests
26
+ from rich.console import _is_jupyter
26
27
  from rich.progress import (
27
28
  BarColumn,
28
29
  DownloadColumn,
@@ -53,13 +54,13 @@ from truefoundry.ml.autogen.client import ( # type: ignore[attr-defined]
53
54
  RunArtifactsApi,
54
55
  SignedURLDto,
55
56
  )
56
- from truefoundry.ml.env_vars import DISABLE_MULTIPART_UPLOAD
57
- from truefoundry.ml.exceptions import MlFoundryException
58
- from truefoundry.ml.logger import logger
59
- from truefoundry.ml.services.utils import (
57
+ from truefoundry.ml.clients.utils import (
60
58
  augmented_raise_for_status,
61
59
  cloud_storage_http_request,
62
60
  )
61
+ from truefoundry.ml.env_vars import DISABLE_MULTIPART_UPLOAD
62
+ from truefoundry.ml.exceptions import MlFoundryException
63
+ from truefoundry.ml.logger import logger
63
64
  from truefoundry.ml.session import _get_api_client
64
65
  from truefoundry.pydantic_v1 import BaseModel, root_validator
65
66
 
@@ -91,6 +92,39 @@ _GENERATE_SIGNED_URL_BATCH_SIZE = 50
91
92
  DEFAULT_PRESIGNED_URL_EXPIRY_TIME = 3600
92
93
 
93
94
 
95
+ def _get_relpath_if_in_tempdir(path: str) -> str:
96
+ tempdir = tempfile.gettempdir()
97
+ if path.startswith(tempdir):
98
+ return os.path.relpath(path, tempdir)
99
+ return path
100
+
101
+
102
+ def _can_display_progress(user_choice: Optional[bool] = None) -> bool:
103
+ if user_choice is False:
104
+ return False
105
+
106
+ if sys.stdout.isatty():
107
+ return True
108
+ elif _is_jupyter():
109
+ try:
110
+ from IPython.display import display # noqa: F401
111
+ from ipywidgets import Output # noqa: F401
112
+
113
+ return True
114
+ except ImportError:
115
+ logger.warning(
116
+ "Detected Jupyter Environment. Install `ipywidgets` to display live progress bars.",
117
+ )
118
+ if user_choice is True:
119
+ logger.warning(
120
+ "`progress` argument is set to True but did not detect tty "
121
+ "or jupyter environment with ipywidgets installed. "
122
+ "Progress bars may not be displayed. "
123
+ )
124
+ return True
125
+ return False
126
+
127
+
94
128
  def relative_path_to_artifact_path(path):
95
129
  if os.path == posixpath:
96
130
  return path
@@ -206,7 +240,7 @@ def _signed_url_upload_file(
206
240
  return
207
241
 
208
242
  task_progress_bar = progress_bar.add_task(
209
- f"[green]Uploading {local_file}:", start=True
243
+ f"[green]Uploading {_get_relpath_if_in_tempdir(local_file)}:", start=True
210
244
  )
211
245
 
212
246
  def callback(length):
@@ -304,7 +338,7 @@ def _s3_compatible_multipart_upload(
304
338
  parts = []
305
339
 
306
340
  multi_part_upload_progress = progress_bar.add_task(
307
- f"[green]Uploading {local_file}:", start=True
341
+ f"[green]Uploading {_get_relpath_if_in_tempdir(local_file)}:", start=True
308
342
  )
309
343
 
310
344
  def upload(part_number: int, seek: int) -> None:
@@ -315,7 +349,7 @@ def _s3_compatible_multipart_upload(
315
349
  local_file,
316
350
  )
317
351
  response = _file_part_upload(
318
- url=multipart_upload.part_signed_urls[part_number].url,
352
+ url=multipart_upload.part_signed_urls[part_number].signed_url,
319
353
  file_path=local_file,
320
354
  seek=seek,
321
355
  length=multipart_info.part_size,
@@ -374,7 +408,7 @@ def _azure_multi_part_upload(
374
408
  abort_event = abort_event or Event()
375
409
 
376
410
  multi_part_upload_progress = progress_bar.add_task(
377
- f"[green]Uploading {local_file}:", start=True
411
+ f"[green]Uploading {_get_relpath_if_in_tempdir(local_file)}:", start=True
378
412
  )
379
413
 
380
414
  def upload(part_number: int, seek: int):
@@ -385,7 +419,7 @@ def _azure_multi_part_upload(
385
419
  local_file,
386
420
  )
387
421
  _file_part_upload(
388
- url=multipart_upload.part_signed_urls[part_number].url,
422
+ url=multipart_upload.part_signed_urls[part_number].signed_url,
389
423
  file_path=local_file,
390
424
  seek=seek,
391
425
  length=multipart_info.part_size,
@@ -527,8 +561,7 @@ class MlFoundryArtifactsRepository:
527
561
  def log_artifacts( # noqa: C901
528
562
  self, local_dir, artifact_path=None, progress=None
529
563
  ):
530
- if progress is None:
531
- progress = sys.stdout.isatty()
564
+ show_progress = _can_display_progress(progress)
532
565
 
533
566
  dest_path = artifact_path or ""
534
567
  dest_path = dest_path.lstrip(posixpath.sep)
@@ -565,14 +598,15 @@ class MlFoundryArtifactsRepository:
565
598
 
566
599
  with Progress(
567
600
  "[progress.description]{task.description}",
568
- BarColumn(),
601
+ BarColumn(bar_width=None),
569
602
  "[progress.percentage]{task.percentage:>3.0f}%",
570
603
  DownloadColumn(),
571
604
  TransferSpeedColumn(),
572
605
  TimeRemainingColumn(),
573
606
  TimeElapsedColumn(),
574
607
  refresh_per_second=1,
575
- disable=not progress,
608
+ disable=not show_progress,
609
+ expand=True,
576
610
  ) as progress_bar, ThreadPoolExecutor(
577
611
  max_workers=_MAX_WORKERS_FOR_UPLOAD
578
612
  ) as executor:
@@ -647,7 +681,11 @@ class MlFoundryArtifactsRepository:
647
681
  )[0]
648
682
 
649
683
  if progress_bar.disable:
650
- logger.info("Uploading %s to %s", local_file, artifact_path)
684
+ logger.info(
685
+ "Uploading %s to %s",
686
+ _get_relpath_if_in_tempdir(local_file),
687
+ artifact_path,
688
+ )
651
689
 
652
690
  _signed_url_upload_file(
653
691
  signed_url=signed_url,
@@ -668,7 +706,9 @@ class MlFoundryArtifactsRepository:
668
706
  ):
669
707
  if progress_bar.disable:
670
708
  logger.info(
671
- "Uploading %s to %s using multipart upload", local_file, artifact_path
709
+ "Uploading %s to %s using multipart upload",
710
+ _get_relpath_if_in_tempdir(local_file),
711
+ artifact_path,
672
712
  )
673
713
 
674
714
  multipart_upload = self.create_multipart_upload_for_identifier(
@@ -746,7 +786,7 @@ class MlFoundryArtifactsRepository:
746
786
  upload_path = posixpath.join(upload_path, os.path.basename(local_file))
747
787
  with Progress(
748
788
  "[progress.description]{task.description}",
749
- BarColumn(),
789
+ BarColumn(bar_width=None),
750
790
  "[progress.percentage]{task.percentage:>3.0f}%",
751
791
  DownloadColumn(),
752
792
  TransferSpeedColumn(),
@@ -754,6 +794,7 @@ class MlFoundryArtifactsRepository:
754
794
  TimeElapsedColumn(),
755
795
  refresh_per_second=1,
756
796
  disable=True,
797
+ expand=True,
757
798
  ) as progress_bar:
758
799
  self._log_artifact(
759
800
  local_file=local_file,
@@ -769,11 +810,11 @@ class MlFoundryArtifactsRepository:
769
810
 
770
811
  def download_artifacts( # noqa: C901
771
812
  self,
772
- artifact_path,
773
- dst_path=None,
813
+ artifact_path: str,
814
+ dst_path: Optional[str] = None,
774
815
  overwrite: bool = False,
775
816
  progress: Optional[bool] = None,
776
- ):
817
+ ) -> str:
777
818
  """
778
819
  Download an artifact file or directory to a local directory if applicable, and return a
779
820
  local path for it. The caller is responsible for managing the lifecycle of the downloaded artifacts.
@@ -791,8 +832,7 @@ class MlFoundryArtifactsRepository:
791
832
  str: Absolute path of the local filesystem location containing the desired artifacts.
792
833
  """
793
834
 
794
- if progress is None:
795
- progress = sys.stdout.isatty()
835
+ show_progress = _can_display_progress()
796
836
 
797
837
  is_dir_temp = False
798
838
  if dst_path is None:
@@ -829,7 +869,8 @@ class MlFoundryArtifactsRepository:
829
869
  TimeRemainingColumn(),
830
870
  TimeElapsedColumn(),
831
871
  refresh_per_second=1,
832
- disable=not progress,
872
+ disable=not show_progress,
873
+ expand=True,
833
874
  )
834
875
 
835
876
  try:
@@ -74,9 +74,6 @@ from truefoundry.ml.autogen.client.models.authorize_user_for_model_request_dto i
74
74
  from truefoundry.ml.autogen.client.models.authorize_user_for_model_version_request_dto import (
75
75
  AuthorizeUserForModelVersionRequestDto,
76
76
  )
77
- from truefoundry.ml.autogen.client.models.backfill_default_storage_integration_id_request_dto import (
78
- BackfillDefaultStorageIntegrationIdRequestDto,
79
- )
80
77
  from truefoundry.ml.autogen.client.models.blob_storage_reference import (
81
78
  BlobStorageReference,
82
79
  )