truefoundry 0.4.4rc6__py3-none-any.whl → 0.4.4rc8__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.

@@ -3,12 +3,17 @@ from enum import Enum
3
3
  from typing import Any, Dict, List, Optional
4
4
  from urllib.parse import urlencode, urljoin
5
5
 
6
- import requests
7
6
  from requests.exceptions import RequestException
8
7
 
9
8
  from truefoundry.common.constants import ENV_VARS
9
+ from truefoundry.common.request_utils import requests_retry_session
10
+ from truefoundry.common.utils import log_time
10
11
  from truefoundry.pydantic_v1 import BaseModel, Field
11
12
 
13
+ # TODO: Move print statements to logger
14
+ # TODO: Move these constants to the constants module
15
+ REQUEST_TIMEOUT = 3600
16
+
12
17
  DEFAULT_TTL = ENV_VARS.TFY_INTERNAL_SIGNED_URL_SERVER_DEFAULT_TTL
13
18
  MAX_TIMEOUT = ENV_VARS.TFY_INTERNAL_SIGNED_URL_SERVER_MAX_TIMEOUT
14
19
 
@@ -69,12 +74,18 @@ class SignedURLClient:
69
74
  self.base_url = base_url or ENV_VARS.TFY_INTERNAL_SIGNED_URL_SERVER_HOST
70
75
  self.token = token or ENV_VARS.TFY_INTERNAL_SIGNED_URL_SERVER_TOKEN
71
76
  self.ttl = ttl
77
+ self.max_retries: int = 3
78
+ self.retry_backoff_factor: float = 0.3
79
+ self.session = requests_retry_session(
80
+ retries=self.max_retries, backoff_factor=self.retry_backoff_factor
81
+ )
72
82
 
73
83
  self.headers = {
74
84
  "Authorization": f"Bearer {self.token}",
75
85
  "Content-Type": "application/json",
76
86
  }
77
87
 
88
+ @log_time
78
89
  def _make_request(
79
90
  self, endpoint: str, method: str = "GET", payload: Optional[Dict] = None
80
91
  ) -> Dict:
@@ -94,7 +105,7 @@ class SignedURLClient:
94
105
  """
95
106
  url = urljoin(self.base_url, endpoint)
96
107
  try:
97
- response = requests.request(
108
+ response = self.session.request(
98
109
  method, url, headers=self.headers, json=payload, timeout=MAX_TIMEOUT
99
110
  )
100
111
  response.raise_for_status()
@@ -110,14 +121,15 @@ class SignedURLClient:
110
121
  endpoint_with_params = f"{endpoint.value}?{query_string}"
111
122
  return self._make_request(endpoint_with_params)
112
123
 
124
+ @log_time
113
125
  def _upload_data(self, signed_url: str, data: Any) -> None:
114
126
  """Helper method to upload data to the signed URL."""
115
127
  try:
116
- # TODO: Add TIMEOUT to this request
117
- response = requests.put(
128
+ response = self.session.put(
118
129
  signed_url,
119
130
  headers={"Content-Type": "application/octet-stream"},
120
131
  data=data,
132
+ timeout=REQUEST_TIMEOUT,
121
133
  )
122
134
  response.raise_for_status()
123
135
  except Exception as e:
@@ -133,6 +145,7 @@ class SignedURLClient:
133
145
  self._upload_data(pre_signed_object_dto.signed_url, data)
134
146
  return storage_uri
135
147
 
148
+ @log_time
136
149
  def upload(self, file_path: str, storage_uri: str) -> str:
137
150
  """Upload a file to the specified storage path using a signed URL."""
138
151
  print(f"Uploading {file_path} to {storage_uri}")
@@ -145,6 +158,7 @@ class SignedURLClient:
145
158
  self._upload_data(pre_signed_object_dto.signed_url, file)
146
159
  return storage_uri
147
160
 
161
+ @log_time
148
162
  def _download_file(
149
163
  self, signed_url: str, local_path: Optional[str] = None
150
164
  ) -> Optional[bytes]:
@@ -158,25 +172,21 @@ class SignedURLClient:
158
172
  Optional[bytes]: The content of the downloaded file if local_path is None; otherwise, None.
159
173
  """
160
174
  try:
161
- # TODO: Add TIMEOUT to this request
162
- response = requests.get(
163
- signed_url,
164
- stream=True,
165
- headers=self.headers,
175
+ response = self.session.get(
176
+ signed_url, stream=True, headers=self.headers, timeout=REQUEST_TIMEOUT
166
177
  )
167
178
  response.raise_for_status()
168
-
169
179
  if local_path:
170
180
  with open(local_path, "wb") as file:
171
181
  for chunk in response.iter_content(chunk_size=8192):
172
182
  file.write(chunk)
173
183
  return None # File saved successfully; no need to return content.
174
-
175
184
  return response.content # Return the content if not saving to a local path.
176
185
 
177
- except requests.RequestException as e:
186
+ except RequestException as e:
178
187
  raise RuntimeError(f"Failed to download file from {signed_url}: {e}") from e
179
188
 
189
+ @log_time
180
190
  def download(self, storage_uri: str, local_path: str) -> Optional[str]:
181
191
  """Download a file from the specified storage path to a local path using a signed URL.
182
192
 
@@ -194,7 +204,7 @@ class SignedURLClient:
194
204
  )
195
205
  presigned_object = SignedURLAPIResponseDto.parse_obj(response)
196
206
  self._download_file(presigned_object.signed_url, local_path)
197
- return local_path # Indicate successful download.
207
+ return local_path
198
208
 
199
209
  def download_to_bytes(self, storage_uri: str) -> bytes:
200
210
  """Download a file from the specified storage path and return it as bytes.
@@ -229,6 +239,7 @@ class SignedURLClient:
229
239
  print(f"Path {uri} is_directory: {response_obj.is_directory}")
230
240
  return response_obj.is_directory
231
241
 
242
+ @log_time
232
243
  def list_files(self, path: str, detail: bool = False, max_results: int = 1000):
233
244
  """List files in the specified directory."""
234
245
  token = ""
@@ -9,19 +9,24 @@ from fsspec.spec import DEFAULT_CALLBACK, AbstractBufferedFile, AbstractFileSyst
9
9
 
10
10
  from truefoundry.common.constants import ENV_VARS
11
11
  from truefoundry.common.tfy_signed_url_client import SignedURLClient
12
+ from truefoundry.common.utils import log_time
12
13
 
13
14
 
14
15
  class SignedURLFileSystem(AbstractFileSystem):
15
- def __init__(self, base_url: Optional[str] = None, token: Optional[str] = None):
16
+ def __init__(
17
+ self, base_url: Optional[str] = None, token: Optional[str] = None, **kwargs
18
+ ):
16
19
  super().__init__()
17
20
  base_url = base_url or ENV_VARS.TFY_INTERNAL_SIGNED_URL_SERVER_HOST
18
21
  token = token or ENV_VARS.TFY_INTERNAL_SIGNED_URL_SERVER_TOKEN
19
22
  self.client = SignedURLClient(base_url, token)
20
23
 
24
+ @log_time
21
25
  def exists(self, path, **kwargs):
22
26
  """Is there a file at the given path"""
23
27
  return self.client.exists(path)
24
28
 
29
+ @log_time
25
30
  def get(
26
31
  self,
27
32
  rpath,
@@ -78,6 +83,7 @@ class SignedURLFileSystem(AbstractFileSystem):
78
83
  target_local_path = target_local_path + rpath.rsplit("/")[-1]
79
84
  self.client.download(storage_uri=rpath, local_path=target_local_path)
80
85
 
86
+ @log_time
81
87
  def put(
82
88
  self,
83
89
  lpath,
@@ -123,6 +129,7 @@ class SignedURLFileSystem(AbstractFileSystem):
123
129
  # Handle single file upload
124
130
  return self.client.upload(file_path=lpath, storage_uri=rpath)
125
131
 
132
+ @log_time
126
133
  def isdir(self, path):
127
134
  """Is this entry directory-like?"""
128
135
  return self.client.is_directory(path)
@@ -173,6 +180,7 @@ class SignedURLFileSystem(AbstractFileSystem):
173
180
  # Upload the content to the remote file system
174
181
  self.client.upload_from_bytes(content, storage_uri=path)
175
182
 
183
+ @log_time
176
184
  def ls(self, path, detail=True, **kwargs):
177
185
  """List objects at path."""
178
186
  return self.client.list_files(path, detail=detail)
@@ -102,3 +102,17 @@ def resolve_tfy_host(tfy_host: Optional[str] = None) -> str:
102
102
  tfy_host = tfy_host.strip("/")
103
103
  validate_tfy_host(tfy_host)
104
104
  return tfy_host
105
+
106
+
107
+ def log_time(func):
108
+ """Decorator to log the time taken by I/O operations."""
109
+
110
+ @wraps(func)
111
+ def wrapper(*args, **kwargs):
112
+ start_time = time.time()
113
+ result = func(*args, **kwargs)
114
+ elapsed_time = time.time() - start_time
115
+ print(f"{func.__name__} took {elapsed_time:.2f} seconds")
116
+ return result
117
+
118
+ return wrapper
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: truefoundry
3
- Version: 0.4.4rc6
3
+ Version: 0.4.4rc8
4
4
  Summary: Truefoundry CLI
5
5
  Author: Abhishek Choudhary
6
6
  Author-email: abhishek@truefoundry.com
@@ -22,7 +22,6 @@ Requires-Dist: docker (>=6.1.2,<8.0.0)
22
22
  Requires-Dist: fastapi (>=0.56.0,<0.200.0)
23
23
  Requires-Dist: filelock (>=3.8.0,<4.0.0)
24
24
  Requires-Dist: flytekit (==1.12.2) ; extra == "workflow"
25
- Requires-Dist: fsspec (>=2024.9.0,<2025.0.0)
26
25
  Requires-Dist: gitignorefile (>=1.1.2,<2.0.0)
27
26
  Requires-Dist: importlib-metadata (>=4.11.3,<9.0.0)
28
27
  Requires-Dist: importlib-resources (>=5.2.0,<7.0.0)
@@ -34,9 +34,9 @@ truefoundry/common/entities.py,sha256=8O-EGPk4PKqnyoFMKUTxISCU19rz0KBnfRDJU695Dh
34
34
  truefoundry/common/exceptions.py,sha256=ePpiQ_zmWe4e94gOgeMiyP_AZnKwjEBfyXsB5ScGYcI,329
35
35
  truefoundry/common/request_utils.py,sha256=5xw4YGUcMf71Ncal3OfFCa-PoWDIvG3hYGCDa4Da4OI,2854
36
36
  truefoundry/common/servicefoundry_client.py,sha256=2fxmgCM-ckFHpnm6n_mL-5Z8RWN_q-dYVvFC29bkYSg,3120
37
- truefoundry/common/tfy_signed_url_client.py,sha256=zqGIG7L6roPdSSdZ5IVTIVjYsOJsWvMa8SMkYttkg70,9401
38
- truefoundry/common/tfy_signed_url_fs.py,sha256=14RJWXeXy2ADqHTfVvBtb7qtQwULxOMF8a1Jrgmgb04,7989
39
- truefoundry/common/utils.py,sha256=MYFjNtHGqauqhj9tmbdErCJR49AfXDwg-5kYbBh8HpI,3258
37
+ truefoundry/common/tfy_signed_url_client.py,sha256=wD8R88wxECvHsHo_BJSeOODLylmJjksZt8iF9pUAd4w,9822
38
+ truefoundry/common/tfy_signed_url_fs.py,sha256=sMrpRnlmVin9q8kfv5iVJZGD6aZUgYKlCXxjDx8lKm4,8129
39
+ truefoundry/common/utils.py,sha256=vacYbVTEvcEY4niH4C9Wb_aCeaGgh2un3_ApAt556VQ,3621
40
40
  truefoundry/deploy/__init__.py,sha256=ugawKF2G02EmEXX35oZ2tec12d9oWN28Sf6mtGGIERY,2281
41
41
  truefoundry/deploy/auto_gen/models.py,sha256=4MaxkG2_5Wg6avaZRlK0D4JiVEM5rk3NU0BCiTx8VyU,82477
42
42
  truefoundry/deploy/builder/__init__.py,sha256=1qjHMNBE1poRCZW0WrG46dFM1f1IlivD5352qzsioMU,4953
@@ -342,7 +342,7 @@ truefoundry/workflow/map_task.py,sha256=2m3qGXQ90k9LdS45q8dqCCECc3qr8t2m_LMCVd1m
342
342
  truefoundry/workflow/python_task.py,sha256=SRXRLC4vdBqGjhkwuaY39LEWN6iPCpJAuW17URRdWTY,1128
343
343
  truefoundry/workflow/task.py,sha256=ToitYiKcNzFCtOVQwz1W8sRjbR97eVS7vQBdbgUQtKg,1779
344
344
  truefoundry/workflow/workflow.py,sha256=WaTqUjhwfAXDWu4E5ehuwAxrCbDJkoAf1oWmR2E9Qy0,4575
345
- truefoundry-0.4.4rc6.dist-info/METADATA,sha256=YuV_hYNyXMHOBpjsQSnBnVgRt0bcj3fstht3SkKhPsQ,3146
346
- truefoundry-0.4.4rc6.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
347
- truefoundry-0.4.4rc6.dist-info/entry_points.txt,sha256=TXvUxQkI6zmqJuycPsyxEIMr3oqfDjgrWj0m_9X12x4,95
348
- truefoundry-0.4.4rc6.dist-info/RECORD,,
345
+ truefoundry-0.4.4rc8.dist-info/METADATA,sha256=umX9ghRm2Gvbw8WS3JM_yFm__OVuvFtvvZB18oLE0a4,3101
346
+ truefoundry-0.4.4rc8.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
347
+ truefoundry-0.4.4rc8.dist-info/entry_points.txt,sha256=TXvUxQkI6zmqJuycPsyxEIMr3oqfDjgrWj0m_9X12x4,95
348
+ truefoundry-0.4.4rc8.dist-info/RECORD,,