truss 0.10.9rc520__py3-none-any.whl → 0.10.9rc601__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.

@@ -14,12 +14,19 @@ from .deploy_checkpoints_helpers import (
14
14
  setup_environment_variables_and_secrets,
15
15
  )
16
16
 
17
+ # NB(aghilan): Transformers was recently changed to save a chat_template.jinja file instead of inside the tokenizer_config.json file.
18
+ # Old Models will not have this file, so we check for it and use it if it exists.
19
+ # vLLM will not automatically resolve the chat_template.jinja file, so we need to pass it to the start command.
20
+ # This logic is needed for any models trained using Transformers v4.51.3 or later
17
21
  VLLM_FULL_START_COMMAND = Template(
18
- 'sh -c "{%if envvars %}{{ envvars }} {% endif %}vllm serve {{ model_path }}'
19
- + " --port 8000"
20
- + " --tensor-parallel-size {{ specify_tensor_parallelism }}"
21
- + " --dtype bfloat16"
22
- + '"'
22
+ "sh -c '{% if envvars %}{{ envvars }} {% endif %}"
23
+ 'HF_TOKEN="$$(cat /secrets/hf_access_token)" && export HF_TOKEN && '
24
+ "if [ -f {{ model_path }}/chat_template.jinja ]; then "
25
+ " vllm serve {{ model_path }} --chat-template {{ model_path }}/chat_template.jinja "
26
+ " --port 8000 --tensor-parallel-size {{ specify_tensor_parallelism }} --dtype bfloat16; "
27
+ "else "
28
+ " vllm serve {{ model_path }} --port 8000 --tensor-parallel-size {{ specify_tensor_parallelism }} --dtype bfloat16; "
29
+ "fi'"
23
30
  )
24
31
 
25
32
 
@@ -809,8 +809,9 @@ class ServingImageBuilder(ImageBuilder):
809
809
  data_dir_exists=data_dir.exists(),
810
810
  model_dir_exists=model_dir.exists(),
811
811
  bundled_packages_dir_exists=bundled_packages_dir.exists(),
812
- # Create a sanitized copy of the truss directory for hash calculation
813
- truss_hash=self._calculate_sanitized_truss_hash(build_dir),
812
+ truss_hash=directory_content_hash(
813
+ self._truss_dir, self._spec.hash_ignore_patterns
814
+ ),
814
815
  models=model_files,
815
816
  use_hf_secret=use_hf_secret,
816
817
  cached_files=cached_files,
@@ -831,26 +832,3 @@ class ServingImageBuilder(ImageBuilder):
831
832
  ).strip()
832
833
  docker_file_path = build_dir / MODEL_DOCKERFILE_NAME
833
834
  docker_file_path.write_text(dockerfile_contents)
834
-
835
- def _calculate_sanitized_truss_hash(self, build_dir: Path) -> str:
836
- """Calculate hash from a sanitized copy of the truss directory with runtime fields cleared."""
837
- sanitized_truss_dir = build_dir / "build_model_scaffold"
838
-
839
- # Remove existing copy if it exists
840
- if sanitized_truss_dir.exists():
841
- shutil.rmtree(sanitized_truss_dir)
842
-
843
- # Copy the entire truss directory
844
- shutil.copytree(self._truss_dir, sanitized_truss_dir)
845
-
846
- # Clear runtime fields from the config
847
- config_file_path = sanitized_truss_dir / "config.yaml"
848
- if config_file_path.exists():
849
- truss_config = TrussConfig.from_yaml(config_file_path)
850
- truss_config.clear_runtime_fields()
851
- truss_config.write_to_yaml_file(config_file_path)
852
-
853
- # Calculate hash from the sanitized directory
854
- return directory_content_hash(
855
- sanitized_truss_dir, self._spec.hash_ignore_patterns
856
- )
@@ -59,6 +59,7 @@ class MethodName(str, enum.Enum):
59
59
  CHAT_COMPLETIONS = enum.auto()
60
60
  COMPLETIONS = enum.auto()
61
61
  IS_HEALTHY = enum.auto()
62
+ MESSAGES = enum.auto()
62
63
  POSTPROCESS = enum.auto()
63
64
  PREDICT = enum.auto()
64
65
  PREPROCESS = enum.auto()
@@ -244,6 +245,7 @@ class ModelDescriptor:
244
245
  is_healthy: Optional[MethodDescriptor]
245
246
  completions: Optional[MethodDescriptor]
246
247
  chat_completions: Optional[MethodDescriptor]
248
+ messages: Optional[MethodDescriptor]
247
249
  websocket: Optional[MethodDescriptor]
248
250
 
249
251
  @cached_property
@@ -291,6 +293,7 @@ class ModelDescriptor:
291
293
  setup = cls._safe_extract_descriptor(model_cls, MethodName.SETUP_ENVIRONMENT)
292
294
  completions = cls._safe_extract_descriptor(model_cls, MethodName.COMPLETIONS)
293
295
  chats = cls._safe_extract_descriptor(model_cls, MethodName.CHAT_COMPLETIONS)
296
+ messages = cls._safe_extract_descriptor(model_cls, MethodName.MESSAGES)
294
297
  is_healthy = cls._safe_extract_descriptor(model_cls, MethodName.IS_HEALTHY)
295
298
  if is_healthy and is_healthy.arg_config != ArgConfig.NONE:
296
299
  raise errors.ModelDefinitionError(
@@ -359,6 +362,7 @@ class ModelDescriptor:
359
362
  is_healthy=is_healthy,
360
363
  completions=completions,
361
364
  chat_completions=chats,
365
+ messages=messages,
362
366
  websocket=websocket,
363
367
  )
364
368
 
@@ -925,6 +929,14 @@ class ModelWrapper:
925
929
  )
926
930
  return await self._execute_model_endpoint(inputs, request, descriptor)
927
931
 
932
+ async def messages(
933
+ self, inputs: InputType, request: starlette.requests.Request
934
+ ) -> OutputType:
935
+ descriptor = self._get_descriptor_or_raise(
936
+ self.model_descriptor.messages, MethodName.MESSAGES
937
+ )
938
+ return await self._execute_model_endpoint(inputs, request, descriptor)
939
+
928
940
  async def websocket(self, ws: WebSocket) -> None:
929
941
  descriptor = self.model_descriptor.websocket
930
942
  assert descriptor, "websocket can only be invoked if present on model."
@@ -231,6 +231,13 @@ class BasetenEndpoints:
231
231
  method=self._model.completions, request=request, body_raw=body_raw
232
232
  )
233
233
 
234
+ async def messages(
235
+ self, request: Request, body_raw: bytes = Depends(parse_body)
236
+ ) -> Response:
237
+ return await self._execute_request(
238
+ method=self._model.messages, request=request, body_raw=body_raw
239
+ )
240
+
234
241
  async def websocket(self, ws: WebSocket) -> None:
235
242
  self.check_healthy()
236
243
  trace_ctx = otel_propagate.extract(ws.headers) or None
@@ -428,6 +435,12 @@ class TrussServer:
428
435
  methods=["POST"],
429
436
  tags=["V1"],
430
437
  ),
438
+ FastAPIRoute(
439
+ r"/v1/messages",
440
+ self._endpoints.messages,
441
+ methods=["POST"],
442
+ tags=["V1"],
443
+ ),
431
444
  # Websocket endpoint
432
445
  FastAPIWebSocketRoute(r"/v1/websocket", self._endpoints.websocket),
433
446
  # Endpoint aliases for Sagemaker hosting
@@ -505,8 +505,16 @@ def test_render_vllm_full_truss_config():
505
505
  )
506
506
 
507
507
  result = render_vllm_full_truss_config(deploy_config)
508
-
509
- expected_vllm_command = 'sh -c "HF_TOKEN=$(cat /secrets/hf_token) vllm serve /tmp/training_checkpoints/job123/rank-0/checkpoint-1 --port 8000 --tensor-parallel-size 2 --dtype bfloat16"'
508
+ expected_vllm_command = (
509
+ "sh -c 'HF_TOKEN=$(cat /secrets/hf_token) "
510
+ 'HF_TOKEN="$$(cat /secrets/hf_access_token)" && export HF_TOKEN && '
511
+ "if [ -f /tmp/training_checkpoints/job123/rank-0/checkpoint-1/chat_template.jinja ]; then "
512
+ "vllm serve /tmp/training_checkpoints/job123/rank-0/checkpoint-1 "
513
+ "--chat-template /tmp/training_checkpoints/job123/rank-0/checkpoint-1/chat_template.jinja "
514
+ "--port 8000 --tensor-parallel-size 2 --dtype bfloat16; else "
515
+ "vllm serve /tmp/training_checkpoints/job123/rank-0/checkpoint-1 "
516
+ "--port 8000 --tensor-parallel-size 2 --dtype bfloat16; fi'"
517
+ )
510
518
 
511
519
  assert isinstance(result, truss_config.TrussConfig)
512
520
  assert result.model_name == "test-full-model"
@@ -13,3 +13,6 @@ class Model:
13
13
 
14
14
  def predict(self, input: Dict) -> str:
15
15
  return "predict"
16
+
17
+ def messages(self, input: Dict) -> str:
18
+ return "messages"
@@ -1,6 +1,5 @@
1
1
  from pathlib import Path
2
2
  from typing import Any, List, Optional
3
- import traceback
4
3
 
5
4
  from blake3 import blake3
6
5
 
@@ -20,15 +19,6 @@ def directory_content_hash(
20
19
  underneath. The (root) Directory will have the same hash, even if renamed.
21
20
  """
22
21
  hasher = blake3()
23
- print(f"Calculating hash for {root}, ignore_patterns: {ignore_patterns}")
24
-
25
- # Print caller chain
26
- caller_chain = traceback.extract_stack()
27
- if len(caller_chain) > 1:
28
- print("Caller chain:")
29
- for i, frame in enumerate(caller_chain[:-1]): # Skip the current function
30
- print(f" {i+1}. {frame.filename}:{frame.lineno} in {frame.name}")
31
-
32
22
  paths = list(get_unignored_relative_paths_from_root(root, ignore_patterns))
33
23
  paths.sort()
34
24
  for path in paths:
@@ -36,9 +26,7 @@ def directory_content_hash(
36
26
  absolute_path = root / path
37
27
  if absolute_path.is_file():
38
28
  hasher.update(file_content_hash(absolute_path))
39
- hash_str = hasher.hexdigest()
40
- print(f"Hash for {root}: {hash_str}")
41
- return hash_str
29
+ return hasher.hexdigest()
42
30
 
43
31
 
44
32
  def file_content_hash(file: Path) -> bytes:
@@ -106,6 +106,7 @@ class DockerURLs:
106
106
  self.predict_url = f"{base_url}/v1/models/model:predict"
107
107
  self.completions_url = f"{base_url}/v1/completions"
108
108
  self.chat_completions_url = f"{base_url}/v1/chat/completions"
109
+ self.messages_url = f"{base_url}/v1/messages"
109
110
 
110
111
  self.schema_url = f"{base_url}/v1/models/model/schema"
111
112
  self.metrics_url = f"{base_url}/metrics"
@@ -938,7 +939,6 @@ class TrussHandle:
938
939
 
939
940
  def _update_config(self, **fields_to_update):
940
941
  config = self._spec.config.model_copy(update=fields_to_update)
941
- print(f"Updating config: {fields_to_update}, writing to {self._spec.config_path}")
942
942
  config.write_to_yaml_file(self._spec.config_path)
943
943
  self._spec = TrussSpec(self._truss_dir) # Reload.
944
944
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: truss
3
- Version: 0.10.9rc520
3
+ Version: 0.10.9rc601
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
@@ -25,7 +25,7 @@ truss/cli/train/types.py,sha256=alGtr4Q71GeB65PpGMhsoKygw4k_ncR6MKIP1ioP8rI,951
25
25
  truss/cli/train/deploy_checkpoints/__init__.py,sha256=wL-M2yu8PxO2tFvjwshXAfPnB-5TlvsBp2v_bdzimRU,99
26
26
  truss/cli/train/deploy_checkpoints/deploy_checkpoints.py,sha256=wWFCpaMjM868-f_ChECrGHyMHka1F2VS1pEKPcEw3eM,16667
27
27
  truss/cli/train/deploy_checkpoints/deploy_checkpoints_helpers.py,sha256=7CdYgsxDF7nHITyCGpjjTMeaaOvtlCYwF7NSxpKedS0,1723
28
- truss/cli/train/deploy_checkpoints/deploy_full_checkpoints.py,sha256=pFj7rDcnvb9C4MMfr3wc4aBXfziqFkzw0H883NtQ1Es,3245
28
+ truss/cli/train/deploy_checkpoints/deploy_full_checkpoints.py,sha256=onY-Xk6n1M5H_QGcV47LhiCq1f9p4bOLkHLTJzH8MnI,3970
29
29
  truss/cli/train/deploy_checkpoints/deploy_lora_checkpoints.py,sha256=P91dIAzuhl2GlzmrWwCcYI7uCMT1Lm7C79JQHM_exN4,4442
30
30
  truss/cli/utils/common.py,sha256=aWnla4qMSEz57dRMTl7R-EaScsuEpnQUeziGUaIeqeU,6149
31
31
  truss/cli/utils/output.py,sha256=GNjU85ZAMp5BI6Yij5wYXcaAvpm_kmHV0nHNmdkMxb0,646
@@ -34,7 +34,7 @@ truss/contexts/docker_build_setup.py,sha256=cF4ExZgtYvrWxvyCAaUZUvV_DB_7__MqVomU
34
34
  truss/contexts/truss_context.py,sha256=uS6L-ACHxNk0BsJwESOHh1lA0OGGw0pb33aFKGsASj4,436
35
35
  truss/contexts/image_builder/cache_warmer.py,sha256=wKE5zE3efnEpjmiLqAtQZX1pb2z57aRU0uElOxxb5f4,7434
36
36
  truss/contexts/image_builder/image_builder.py,sha256=IuRgDeeoHVLzIkJvKtX3807eeqEyaroCs_KWDcIHZUg,1461
37
- truss/contexts/image_builder/serving_image_builder.py,sha256=zz0IkoYMsWQquOpiHR-I-Cz54MFyOtvVzkSwCdxouWc,34918
37
+ truss/contexts/image_builder/serving_image_builder.py,sha256=NdjlQDZqKsmFDXx1UqL2HszL4ozPuNC6MFoTbXB5l0w,33886
38
38
  truss/contexts/image_builder/util.py,sha256=y2-CjUKv0XV-0w2sr1fUCflysDJLsoU4oPp6tvvoFnk,1203
39
39
  truss/contexts/local_loader/docker_build_emulator.py,sha256=rmf7I28zksSmHjwvJMx2rIa6xK4KeR5fBm5YFth_fQg,2464
40
40
  truss/contexts/local_loader/dockerfile_parser.py,sha256=GoRJ0Af_3ILyLhjovK5lrCGn1rMxz6W3l681ro17ZzI,1344
@@ -92,9 +92,9 @@ truss/templates/docker_server/proxy.conf.jinja,sha256=Lg-PcZzKflG85exZKHNgW_I6r0
92
92
  truss/templates/docker_server/supervisord.conf.jinja,sha256=CoaSLv0Lr8t1tS_q102IFufNX2lWrlbCHJLjMhYjOwM,1711
93
93
  truss/templates/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
94
94
  truss/templates/server/main.py,sha256=kWXrdD8z8IpamyWxc8qcvd5ck9gM1Kz2QH5qHJCnmOQ,222
95
- truss/templates/server/model_wrapper.py,sha256=k75VVISwwlsx5EGb82UZsu8kCM_i6Yi3-Hd0-Kpm1yo,42055
95
+ truss/templates/server/model_wrapper.py,sha256=3xrEVKdFMCEnBJ4sZB14Vt_kwGoBxUibkFlCfonBOTE,42554
96
96
  truss/templates/server/requirements.txt,sha256=iRR2BEpBQnt-YOiTEKOnaab7tlR4C23V1cuURuIt7ZY,672
97
- truss/templates/server/truss_server.py,sha256=ob_nceeGtFPZzKKdk_ZZGLoZrJOGE6hR52xM1sPR97A,19498
97
+ truss/templates/server/truss_server.py,sha256=FuouBLIQZ3-lsW_FGunY-S7hJ9KUNuqjLMOwYKVx8mE,19945
98
98
  truss/templates/server/common/__init__.py,sha256=qHIqr68L5Tn4mV6S-PbORpcuJ4jmtBR8aCuRTIWDvNo,85
99
99
  truss/templates/server/common/errors.py,sha256=qWeZlmNI8ZGbZbOIp_mtS6IKvUFIzhj3QH8zp-xTp9o,8554
100
100
  truss/templates/server/common/patches.py,sha256=uEOzvDnXsHOkTSa8zygGYuR4GHhrFNVHNQc5peJcwvo,1393
@@ -136,7 +136,7 @@ truss/tests/test_truss_gatherer.py,sha256=bn288OEkC49YY0mhly4cAl410ktZPfElNdWwZy
136
136
  truss/tests/test_truss_handle.py,sha256=-xz9VXkecXDTslmQZ-dmUmQLnvD0uumRqHS2uvGlMBA,30750
137
137
  truss/tests/test_util.py,sha256=hs1bNMkXKEdoPRx4Nw-NAEdoibR92OubZuADGmbiYsQ,1344
138
138
  truss/tests/cli/test_cli.py,sha256=yfbVS5u1hnAmmA8mJ539vj3lhH-JVGUvC4Q_Mbort44,787
139
- truss/tests/cli/train/test_deploy_checkpoints.py,sha256=pPTqyGqvSsrsEHXguo6swLXkVObytLdupfSElqlujPc,25733
139
+ truss/tests/cli/train/test_deploy_checkpoints.py,sha256=yCPE5S4D_92hz692QKYDaHvwye4imuz2e1pd1K1pXkE,26203
140
140
  truss/tests/cli/train/test_train_cli_core.py,sha256=T1Xa6-NRk2nTJGX6sXaA8x4qCwL3Ini72PBI2gW7rYM,7879
141
141
  truss/tests/cli/train/resources/test_deploy_from_checkpoint_config.yml,sha256=GF7r9l0KaeXiUYCPSBpeMPd2QG6PeWWyI12NdbqLOgc,1930
142
142
  truss/tests/contexts/image_builder/test_serving_image_builder.py,sha256=ycOxhGIfe5OVcgqZqJvn1Ca2368AN1KdNmIO0vSZ4ko,22368
@@ -236,7 +236,7 @@ truss/tests/test_data/test_go_custom_server_truss/docker/main.go,sha256=WR3mJU1o
236
236
  truss/tests/test_data/test_openai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
237
237
  truss/tests/test_data/test_openai/config.yaml,sha256=ByY_Smgx0lw24Yj0hqgofEmL3nrGNj7gZE5iBKlvwxk,235
238
238
  truss/tests/test_data/test_openai/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
239
- truss/tests/test_data/test_openai/model/model.py,sha256=GEtIJnWlU1snBid2sS-bZHrjQpP8UzL8tanzyH_tdgE,319
239
+ truss/tests/test_data/test_openai/model/model.py,sha256=NMyZH6QcJv4TMw2Cd8M02wvmwDqlWJB4ZwtD4n8QU0Y,390
240
240
  truss/tests/test_data/test_pyantic_v1/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
241
241
  truss/tests/test_data/test_pyantic_v1/config.yaml,sha256=fqWpH3E4UPEnjvAw6Q9_F5oZZLy69RAfycbgtmCFsXo,270
242
242
  truss/tests/test_data/test_pyantic_v1/requirements.txt,sha256=OpG4JAdJME9VWjoNftdHYg-y94k2gbhqdM1_NwOgcT8,13
@@ -316,13 +316,13 @@ truss/truss_handle/build.py,sha256=BKFV-S57tnWcfRffvQ7SPp78BrjmRy3GhgF6ThaIrDM,3
316
316
  truss/truss_handle/decorators.py,sha256=PUR5w2rl_cvcsVtAUpcYLzNXuOml9R0-wtpXy-9hDPk,407
317
317
  truss/truss_handle/readme_generator.py,sha256=B4XbGwUjzMNOr71DWNAL8kCu5_ZHq7YOM8yVGaOZMSE,716
318
318
  truss/truss_handle/truss_gatherer.py,sha256=Xysl_UnCVhehPfZeHa8p7WFp94ENqh-VVpbuqnCui3A,2870
319
- truss/truss_handle/truss_handle.py,sha256=x-2W2bwJhaVvlUaza7Gt1OHKBW4ykSIbgOR-SAEE-Ss,40977
319
+ truss/truss_handle/truss_handle.py,sha256=pGsrsfCSEa5DmrFAoA5Nxr9TBke0Dr2eaq81Ht82j9U,40940
320
320
  truss/truss_handle/patch/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
321
321
  truss/truss_handle/patch/calc_patch.py,sha256=Qyk1QmacK4jy9Ia8-93L8VtAWJhw15z22DdZUkBKlys,18334
322
322
  truss/truss_handle/patch/constants.py,sha256=pCEi5Pwi8Rnqthrr3VEsWL9EP1P1VV1T8DEYuitHLmc,139
323
323
  truss/truss_handle/patch/custom_types.py,sha256=QklzhgLD_PpvNvNYQCvujAd16eYEaDGfLA1scxk6zsA,3481
324
324
  truss/truss_handle/patch/dir_signature.py,sha256=UCdZCzXkI-l-ae0I0pdmB2bavB9qzhhOKYXyLnDFQZY,921
325
- truss/truss_handle/patch/hash.py,sha256=3FU-eI9tHgqLovKz1-K_LbQps1RIh0VP2mIo1s0wDrc,2570
325
+ truss/truss_handle/patch/hash.py,sha256=0LCV091DJKzkuulQQqgzqPPa2zyeHoa5faXddSKLuqM,2106
326
326
  truss/truss_handle/patch/local_truss_patch_applier.py,sha256=fOHWKt3teYnbqeRsF63FjDRu0iCxMfN5RHWtiDxXHIc,2942
327
327
  truss/truss_handle/patch/signature.py,sha256=8eas8gy6Japd1hrgdmtHmKTTxQmWsbmgKRQQGL2PVuA,858
328
328
  truss/truss_handle/patch/truss_dir_patch_applier.py,sha256=uhhHvKYHn_dpfz0xp4jwO9_qAej5sO3f8of_h-21PP4,3666
@@ -361,8 +361,8 @@ truss_train/definitions.py,sha256=yFQYJoxK2tDBeKFHR-IJz12jU1CtWRXN-ZERh9zjMHo,66
361
361
  truss_train/deployment.py,sha256=zmeJ66kg1Wc7l7bwA_cXqv85uMF77hYl7NPHuhc1NPs,2493
362
362
  truss_train/loader.py,sha256=0o66EjBaHc2YY4syxxHVR4ordJWs13lNXnKjKq2wq0U,1630
363
363
  truss_train/public_api.py,sha256=9N_NstiUlmBuLUwH_fNG_1x7OhGCytZLNvqKXBlStrM,1220
364
- truss-0.10.9rc520.dist-info/METADATA,sha256=gUlOXD6Xe0raLIuYQz9HDDb5mWkV_FB0sFwqlNnD6Rs,6674
365
- truss-0.10.9rc520.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
366
- truss-0.10.9rc520.dist-info/entry_points.txt,sha256=-MwKfHHQHQ6j0HqIgvxrz3CehCmczDLTD-OsRHnjjuU,130
367
- truss-0.10.9rc520.dist-info/licenses/LICENSE,sha256=FTqGzu85i-uw1Gi8E_o0oD60bH9yQ_XIGtZbA1QUYiw,1064
368
- truss-0.10.9rc520.dist-info/RECORD,,
364
+ truss-0.10.9rc601.dist-info/METADATA,sha256=lVGZYss-iZy1X7xth17tJozGiJKzPr6cpFKm9kb-7qY,6674
365
+ truss-0.10.9rc601.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
366
+ truss-0.10.9rc601.dist-info/entry_points.txt,sha256=-MwKfHHQHQ6j0HqIgvxrz3CehCmczDLTD-OsRHnjjuU,130
367
+ truss-0.10.9rc601.dist-info/licenses/LICENSE,sha256=FTqGzu85i-uw1Gi8E_o0oD60bH9yQ_XIGtZbA1QUYiw,1064
368
+ truss-0.10.9rc601.dist-info/RECORD,,