truss 0.11.9rc5__py3-none-any.whl → 0.11.9rc500__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 truss might be problematic. Click here for more details.

@@ -17,7 +17,9 @@ class LogWatcher(ABC):
17
17
  # NB(nikhil): we add buffer for clock skew, so this helps us detect duplicates.
18
18
  # TODO(nikhil): clean up hashes so this doesn't grow indefinitely.
19
19
  _log_hashes: set[str] = set()
20
- _last_poll_time: Optional[int] = None
20
+
21
+ _last_poll_time_ms: Optional[int] = None
22
+ _last_log_time_ms: Optional[int] = None
21
23
 
22
24
  def __init__(self, api: BasetenApi):
23
25
  self.api = api
@@ -26,37 +28,54 @@ class LogWatcher(ABC):
26
28
  log_str = f"{log.timestamp}-{log.message}-{log.replica}"
27
29
  return hashlib.sha256(log_str.encode("utf-8")).hexdigest()
28
30
 
29
- def _poll(self) -> Iterator[ParsedLog]:
30
- start_epoch: Optional[int] = None
31
- now = int(time.time() * 1000)
32
- if self._last_poll_time is not None:
33
- start_epoch = self._last_poll_time - CLOCK_SKEW_BUFFER_MS
31
+ def get_start_epoch_ms(self, now_ms: int) -> Optional[int]:
32
+ if self._last_poll_time_ms:
33
+ return self._last_poll_time_ms - CLOCK_SKEW_BUFFER_MS
34
+
35
+ return None
34
36
 
37
+ def fetch_and_parse_logs(
38
+ self, start_epoch_millis: Optional[int], end_epoch_millis: Optional[int]
39
+ ) -> Iterator[ParsedLog]:
35
40
  api_logs = self.fetch_logs(
36
- start_epoch_millis=start_epoch, end_epoch_millis=now + CLOCK_SKEW_BUFFER_MS
41
+ start_epoch_millis=start_epoch_millis, end_epoch_millis=end_epoch_millis
37
42
  )
38
43
 
39
44
  parsed_logs = parse_logs(api_logs)
45
+
40
46
  for log in parsed_logs:
41
- h = self._hash_log(log)
42
- if h not in self._log_hashes:
47
+ if (h := self._hash_log(log)) not in self._log_hashes:
43
48
  self._log_hashes.add(h)
49
+
44
50
  yield log
45
51
 
46
- self._last_poll_time = now
52
+ def poll(self) -> Iterator[ParsedLog]:
53
+ now_ms = int(time.time() * 1000)
54
+ start_epoch_ms = self.get_start_epoch_ms(now_ms)
55
+
56
+ for log in self.fetch_and_parse_logs(
57
+ start_epoch_millis=start_epoch_ms,
58
+ end_epoch_millis=now_ms + CLOCK_SKEW_BUFFER_MS,
59
+ ):
60
+ yield log
61
+
62
+ epoch_ns = int(log.timestamp)
63
+ self._last_log_time_ms = int(epoch_ns / 1e6)
64
+
65
+ self._last_poll_time_ms = now_ms
47
66
 
48
67
  def watch(self) -> Iterator[ParsedLog]:
49
68
  self.before_polling()
50
69
  with console.status("Polling logs", spinner="aesthetic"):
51
70
  while True:
52
- for log in self._poll():
71
+ for log in self.poll():
53
72
  yield log
54
73
  if self._log_hashes:
55
74
  break
56
75
  time.sleep(POLL_INTERVAL_SEC)
57
76
 
58
77
  while self.should_poll_again():
59
- for log in self._poll():
78
+ for log in self.poll():
60
79
  yield log
61
80
  time.sleep(POLL_INTERVAL_SEC)
62
81
  self.post_poll()
@@ -1,9 +1,12 @@
1
+ from functools import cached_property
1
2
  from typing import Any, List, Optional
2
3
 
3
4
  from truss.cli.logs.base_watcher import LogWatcher
4
5
  from truss.remote.baseten.api import BasetenApi
5
6
  from truss.remote.baseten.utils.status import MODEL_RUNNING_STATES
6
7
 
8
+ MAX_LOOK_BACK_MS = 1000 * 60 * 60 # 1 hour.
9
+
7
10
 
8
11
  class ModelDeploymentLogWatcher(LogWatcher):
9
12
  _model_id: str
@@ -25,11 +28,31 @@ class ModelDeploymentLogWatcher(LogWatcher):
25
28
  self._model_id, self._deployment_id, start_epoch_millis, end_epoch_millis
26
29
  )
27
30
 
31
+ def get_start_epoch_ms(self, now_ms: int) -> Optional[int]:
32
+ # NOTE(Tyron): If there can be multiple replicas,
33
+ # we can't use a timestamp cursor to poll for logs.
34
+ if not self._is_development:
35
+ return super().get_start_epoch_ms(now_ms)
36
+
37
+ # Cursor logic.
38
+
39
+ if self._last_log_time_ms:
40
+ return max(self._last_log_time_ms, now_ms - MAX_LOOK_BACK_MS)
41
+
42
+ return None
43
+
28
44
  def should_poll_again(self) -> bool:
29
45
  return self._current_status in MODEL_RUNNING_STATES
30
46
 
47
+ def _get_deployment(self) -> Any:
48
+ return self.api.get_deployment(self._model_id, self._deployment_id)
49
+
31
50
  def _get_current_status(self) -> str:
32
- return self.api.get_deployment(self._model_id, self._deployment_id)["status"]
51
+ return self._get_deployment()["status"]
52
+
53
+ @cached_property
54
+ def _is_development(self) -> bool:
55
+ return self._get_deployment()["is_development"]
33
56
 
34
57
  def post_poll(self) -> None:
35
58
  self._current_status = self._get_current_status()
@@ -84,10 +84,9 @@ def create_app(base_config: Dict):
84
84
  base_url=f"http://localhost:{app_state.inference_server_port}", limits=limits
85
85
  )
86
86
 
87
- pip_path = getattr(app_state, "pip_path", None)
88
-
87
+ uv_path = getattr(app_state, "uv_path", None)
89
88
  patch_applier = ModelContainerPatchApplier(
90
- Path(app_state.inference_server_home), app_logger, pip_path
89
+ Path(app_state.inference_server_home), app_logger, uv_path
91
90
  )
92
91
 
93
92
  oversee_inference_server = getattr(app_state, "oversee_inference_server", True)
@@ -22,8 +22,6 @@ from helpers.truss_patch.model_code_patch_applier import apply_code_patch
22
22
  from truss.base.truss_config import ExternalData, ExternalDataItem, TrussConfig
23
23
  from truss.util.download import download_external_data
24
24
 
25
- DEFAULT_PYTHON_EXECUTABLE = "python3"
26
-
27
25
 
28
26
  class ModelContainerPatchApplier:
29
27
  """Applies patches to container running a truss.
@@ -49,10 +47,12 @@ class ModelContainerPatchApplier:
49
47
  if uv_path is not None:
50
48
  self._uv_path_cached = uv_path
51
49
 
52
- # NB(nikhil): Get full path to the python interpreter for pip patches.
53
50
  self._python_executable = self._get_python_executable()
54
51
 
55
52
  def _get_python_executable(self) -> str:
53
+ # NB(nikhil): `uv` requires the full path to the python interpreter for patching
54
+ # python modules. We expect PYTHON_EXECUTABLE to exist in all development images, but
55
+ # we fallback to python3 as a default.
56
56
  python_executable = os.environ.get("PYTHON_EXECUTABLE", "python3")
57
57
  full_executable_path = shutil.which(python_executable)
58
58
  return full_executable_path or python_executable
@@ -111,7 +111,6 @@ class ModelContainerPatchApplier:
111
111
  "pip",
112
112
  "uninstall",
113
113
  python_requirement_patch.requirement,
114
- "--yes",
115
114
  "--python",
116
115
  self._python_executable,
117
116
  ],
@@ -177,14 +176,8 @@ class ModelContainerPatchApplier:
177
176
 
178
177
 
179
178
  def _identify_uv_path() -> str:
180
- candidate_paths: list[Path] = [
181
- Path.home() / ".local" / "bin" / "uv",
182
- Path("/usr/local/bin/uv"),
183
- Path.home() / ".cargo" / "bin" / "uv",
184
- ]
185
-
186
- for path in candidate_paths:
187
- if path.exists():
188
- return str(path)
179
+ uv_path = shutil.which("uv")
180
+ if not uv_path:
181
+ raise RuntimeError("Unable to find `uv`, make sure it's installed.")
189
182
 
190
- raise RuntimeError("Unable to find `uv, make sure it's installed.")
183
+ return uv_path
@@ -53,7 +53,7 @@ def app(truss_container_fs, truss_original_hash, ports):
53
53
  "control_server_port": ports["control_server_port"],
54
54
  "inference_server_port": ports["inference_server_port"],
55
55
  "oversee_inference_server": False,
56
- "pip_path": "pip",
56
+ "uv_path": "uv",
57
57
  }
58
58
  )
59
59
  inference_server_controller = control_app.state.inference_server_controller
truss/util/__init__.py ADDED
File without changes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: truss
3
- Version: 0.11.9rc5
3
+ Version: 0.11.9rc500
4
4
  Summary: A seamless bridge from model development to model delivery
5
5
  Project-URL: Repository, https://github.com/basetenlabs/truss
6
6
  Project-URL: Homepage, https://truss.baseten.co
@@ -12,8 +12,8 @@ truss/cli/chains_commands.py,sha256=Kpa5mCg6URAJQE2ZmZfVQFhjBHEitKT28tKiW0H6XAI,
12
12
  truss/cli/cli.py,sha256=PaMkuwXZflkU7sa1tEoT_Zmy-iBkEZs1m4IVqcieaeo,30367
13
13
  truss/cli/remote_cli.py,sha256=G_xCKRXzgkCmkiZJhUFfsv5YSVgde1jLA5LPQitpZgI,1905
14
14
  truss/cli/train_commands.py,sha256=Cfr9-TDE-esQI_R8az5OpLoQyz3Qv38mLsSNwy9znmI,18873
15
- truss/cli/logs/base_watcher.py,sha256=KKyd7lIrdaEeDVt8EtjMioSPGVpLyOcF0ewyzE_GGdQ,2785
16
- truss/cli/logs/model_log_watcher.py,sha256=NACcP-wkcaroYa2Cb9BZC7Yr0554WZa_FSM2LXOf4A8,1263
15
+ truss/cli/logs/base_watcher.py,sha256=vuqteoaMVGX34cgKcETf4X_gOkvnSnDaWz1_pbeFhqs,3343
16
+ truss/cli/logs/model_log_watcher.py,sha256=38vQCcNItfDrTKucvdJ10ZYLOcbGa5ZAKUqUnV4nH34,1971
17
17
  truss/cli/logs/training_log_watcher.py,sha256=r6HRqrLnz-PiKTUXiDYYxg4ZnP8vYcXlEX1YmgHhzlo,1173
18
18
  truss/cli/logs/utils.py,sha256=z-U_FG4BUzdZLbE3BnXb4DZQ0zt3LSZ3PiQpLaDuc3o,1031
19
19
  truss/cli/train/common.py,sha256=xTR41U5FeSndXfNBBHF9wF5XwZH1sOIVFlv-XHjsKIU,1547
@@ -73,7 +73,7 @@ truss/templates/copy_cache_files.Dockerfile.jinja,sha256=Os5zFdYLZ_AfCRGq4RcpVTO
73
73
  truss/templates/docker_server_requirements.txt,sha256=PyhOPKAmKW1N2vLvTfLMwsEtuGpoRrbWuNo7tT6v2Mc,18
74
74
  truss/templates/server.Dockerfile.jinja,sha256=CUYnF_hgxPGq2re7__0UPWlwzOHMoFkxp6NVKi3U16s,7071
75
75
  truss/templates/control/requirements.txt,sha256=nqqNmlTwFeV8sV4fqwItwzzd_egADBP_e-cEopXBJ4k,358
76
- truss/templates/control/control/application.py,sha256=KVnOf_ZUPBifgnyfUhOSW9AkhPuWhECUQybSWthm_iY,5126
76
+ truss/templates/control/control/application.py,sha256=GxjRglKQhug0bOJEeBcj9YJWJzHVAnAybvgzDcopG5k,5122
77
77
  truss/templates/control/control/endpoints.py,sha256=KzqsLVNJE6r6TCPW8D5FMCtsfHadTwR15A3z_viGxmM,11782
78
78
  truss/templates/control/control/server.py,sha256=R4Y219i1dcz0kkksN8obLoX-YXWGo9iW1igindyG50c,3128
79
79
  truss/templates/control/control/helpers/context_managers.py,sha256=W6dyFgLBhPa5meqrOb3w_phMtKfaJI-GhwUfpiycDc8,413
@@ -84,7 +84,7 @@ truss/templates/control/control/helpers/inference_server_process_controller.py,s
84
84
  truss/templates/control/control/helpers/inference_server_starter.py,sha256=Fz2Puijro6Cc5cvTsAqOveNJbBQR_ARYJXl4lvETJ8Y,2633
85
85
  truss/templates/control/control/helpers/truss_patch/__init__.py,sha256=CXZdUV_ylqLTJrKuFpvSnUT6PUFrZrMF2y6jiHbdaKU,998
86
86
  truss/templates/control/control/helpers/truss_patch/model_code_patch_applier.py,sha256=LTIIADLz0wRn7V49j64dU1U7Hbta9YLde3pb5YZWvzQ,2001
87
- truss/templates/control/control/helpers/truss_patch/model_container_patch_applier.py,sha256=VsOJYH40zv50bMDgaKe8HSRVju2kVaYou4NG25phKfE,7191
87
+ truss/templates/control/control/helpers/truss_patch/model_container_patch_applier.py,sha256=9bWoleD_dfQHokW5qgC5DyvAQPVhSku3tUqrVKQsQ3w,7091
88
88
  truss/templates/control/control/helpers/truss_patch/requirement_name_identifier.py,sha256=CL3KEAj4B3ApMQShd7TI5umXVbazLZY5StrNlwHwWtc,1995
89
89
  truss/templates/control/control/helpers/truss_patch/system_packages.py,sha256=IYh1CVU_kooAvtSGXKQDDWnNdOhlv7ENWagsL1wvhgw,208
90
90
  truss/templates/custom/examples.yaml,sha256=2UcCtEdavImWmiCtj31ckBlAKVOwNMC5AwMIIznKDag,48
@@ -166,7 +166,7 @@ truss/tests/remote/baseten/test_remote.py,sha256=y1qSPL1t7dBeYI3xMFn436fttG7wkYd
166
166
  truss/tests/remote/baseten/test_service.py,sha256=ufZbtQlBNIzFCxRt_iE-APLpWbVw_3ViUpSh6H9W5nU,1945
167
167
  truss/tests/templates/control/control/conftest.py,sha256=euDFh0AhcHP-vAmTzi1Qj3lymnplDTgvtbt4Ez_lfpw,654
168
168
  truss/tests/templates/control/control/test_endpoints.py,sha256=HIlRYOicsdHD8r_V5gHpZWybDC26uwXJfbvCohdE3HI,3751
169
- truss/tests/templates/control/control/test_server.py,sha256=I4iIywlpXmlKC0SbQLfx4rX4d_uzUxUZj6h2x_7vytE,9151
169
+ truss/tests/templates/control/control/test_server.py,sha256=0D0OMwZ-9jZRxxHoiQYij0RBMenuA9o29LlwNzd04Vk,9149
170
170
  truss/tests/templates/control/control/test_server_integration.py,sha256=kvhgN1OGF5SZ1JFeg6qwbcrTy-Vr7B2JSP2z507ahxo,11925
171
171
  truss/tests/templates/control/control/helpers/test_context_managers.py,sha256=3LoonRaKu_UvhaWs1eNmEQCZq-iJ3aIjI0Mn4amC8Bw,283
172
172
  truss/tests/templates/control/control/helpers/test_model_container_patch_applier.py,sha256=jhPgExGFF42iuWPM9ry93dnpF765d-CGTCIhbswK0hk,5730
@@ -335,6 +335,7 @@ truss/truss_handle/patch/local_truss_patch_applier.py,sha256=fOHWKt3teYnbqeRsF63
335
335
  truss/truss_handle/patch/signature.py,sha256=8eas8gy6Japd1hrgdmtHmKTTxQmWsbmgKRQQGL2PVuA,858
336
336
  truss/truss_handle/patch/truss_dir_patch_applier.py,sha256=uhhHvKYHn_dpfz0xp4jwO9_qAej5sO3f8of_h-21PP4,3666
337
337
  truss/util/.truss_ignore,sha256=jpQA9ou-r_JEIcEHsUqGLHhir_m3d4IPGNyzKXtS-2g,3131
338
+ truss/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
338
339
  truss/util/docker.py,sha256=6PD7kMBBrOjsdvgkuSv7JMgZbe3NoJIeGasljMm2SwA,3934
339
340
  truss/util/download.py,sha256=1lfBwzyaNLEp7SAVrBd9BX5inZpkCVp8sBnS9RNoiJA,2521
340
341
  truss/util/env_vars.py,sha256=7Bv686eER71Barrs6fNamk_TrTJGmu9yV2TxaVmupn0,1232
@@ -369,8 +370,8 @@ truss_train/deployment.py,sha256=lWWANSuzBWu2M4oK4qD7n-oVR1JKdmw2Pn5BJQHg-Ck,307
369
370
  truss_train/loader.py,sha256=0o66EjBaHc2YY4syxxHVR4ordJWs13lNXnKjKq2wq0U,1630
370
371
  truss_train/public_api.py,sha256=9N_NstiUlmBuLUwH_fNG_1x7OhGCytZLNvqKXBlStrM,1220
371
372
  truss_train/restore_from_checkpoint.py,sha256=8hdPm-WSgkt74HDPjvCjZMBpvA9MwtoYsxVjOoa7BaM,1176
372
- truss-0.11.9rc5.dist-info/METADATA,sha256=DVCMx2eswWwbB5hv2xUPXB_JMgZt204AyQ41l8DRlOM,6680
373
- truss-0.11.9rc5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
374
- truss-0.11.9rc5.dist-info/entry_points.txt,sha256=-MwKfHHQHQ6j0HqIgvxrz3CehCmczDLTD-OsRHnjjuU,130
375
- truss-0.11.9rc5.dist-info/licenses/LICENSE,sha256=FTqGzu85i-uw1Gi8E_o0oD60bH9yQ_XIGtZbA1QUYiw,1064
376
- truss-0.11.9rc5.dist-info/RECORD,,
373
+ truss-0.11.9rc500.dist-info/METADATA,sha256=eNLITceNhpjLM8bGpJAOq_cBWJEPzg02P9H60QHx1uw,6682
374
+ truss-0.11.9rc500.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
375
+ truss-0.11.9rc500.dist-info/entry_points.txt,sha256=-MwKfHHQHQ6j0HqIgvxrz3CehCmczDLTD-OsRHnjjuU,130
376
+ truss-0.11.9rc500.dist-info/licenses/LICENSE,sha256=FTqGzu85i-uw1Gi8E_o0oD60bH9yQ_XIGtZbA1QUYiw,1064
377
+ truss-0.11.9rc500.dist-info/RECORD,,