truss 0.11.8rc2__py3-none-any.whl → 0.11.8rc3__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.
- truss/cli/train/core.py +8 -5
- truss/cli/train_commands.py +63 -8
- truss/templates/base.Dockerfile.jinja +5 -3
- truss/tests/test_data/server.Dockerfile +2 -1
- {truss-0.11.8rc2.dist-info → truss-0.11.8rc3.dist-info}/METADATA +1 -1
- {truss-0.11.8rc2.dist-info → truss-0.11.8rc3.dist-info}/RECORD +9 -9
- {truss-0.11.8rc2.dist-info → truss-0.11.8rc3.dist-info}/WHEEL +0 -0
- {truss-0.11.8rc2.dist-info → truss-0.11.8rc3.dist-info}/entry_points.txt +0 -0
- {truss-0.11.8rc2.dist-info → truss-0.11.8rc3.dist-info}/licenses/LICENSE +0 -0
truss/cli/train/core.py
CHANGED
|
@@ -156,7 +156,7 @@ def display_training_projects(projects: list[dict], remote_url: str) -> None:
|
|
|
156
156
|
latest_job = project.get("latest_job") or {}
|
|
157
157
|
if latest_job_id := latest_job.get("id", ""):
|
|
158
158
|
latest_job_link = cli_common.format_link(
|
|
159
|
-
status_page_url(remote_url, latest_job_id), "link"
|
|
159
|
+
status_page_url(remote_url, project["id"], latest_job_id), "link"
|
|
160
160
|
)
|
|
161
161
|
else:
|
|
162
162
|
latest_job_link = ""
|
|
@@ -305,8 +305,11 @@ def display_training_job(
|
|
|
305
305
|
table.add_row("Created", cli_common.format_localized_time(job["created_at"]))
|
|
306
306
|
table.add_row("Last Modified", cli_common.format_localized_time(job["updated_at"]))
|
|
307
307
|
table.add_row(
|
|
308
|
-
"
|
|
309
|
-
cli_common.format_link(
|
|
308
|
+
"Job Page",
|
|
309
|
+
cli_common.format_link(
|
|
310
|
+
status_page_url(remote_url, job["training_project"]["id"], job["id"]),
|
|
311
|
+
"link",
|
|
312
|
+
),
|
|
310
313
|
)
|
|
311
314
|
|
|
312
315
|
# Add error message if present
|
|
@@ -417,8 +420,8 @@ def download_checkpoint_artifacts(
|
|
|
417
420
|
return urls_file
|
|
418
421
|
|
|
419
422
|
|
|
420
|
-
def status_page_url(remote_url: str, training_job_id: str) -> str:
|
|
421
|
-
return f"{remote_url}/training/
|
|
423
|
+
def status_page_url(remote_url: str, project_id: str, training_job_id: str) -> str:
|
|
424
|
+
return f"{remote_url}/training/{project_id}/logs/{training_job_id}"
|
|
422
425
|
|
|
423
426
|
|
|
424
427
|
def _get_all_train_init_example_options(
|
truss/cli/train_commands.py
CHANGED
|
@@ -41,13 +41,14 @@ truss_cli.add_command(train)
|
|
|
41
41
|
|
|
42
42
|
def _print_training_job_success_message(
|
|
43
43
|
job_id: str,
|
|
44
|
+
project_id: str,
|
|
44
45
|
project_name: str,
|
|
45
|
-
job_object: TrainingJob,
|
|
46
|
+
job_object: Optional[TrainingJob],
|
|
46
47
|
remote_provider: BasetenRemote,
|
|
47
48
|
) -> None:
|
|
48
49
|
"""Print success message and helpful commands for a training job."""
|
|
49
50
|
console.print("✨ Training job successfully created!", style="green")
|
|
50
|
-
should_print_cache_summary = (
|
|
51
|
+
should_print_cache_summary = job_object and (
|
|
51
52
|
job_object.runtime.enable_cache
|
|
52
53
|
or job_object.runtime.cache_config
|
|
53
54
|
and job_object.runtime.cache_config.enabled
|
|
@@ -64,7 +65,7 @@ def _print_training_job_success_message(
|
|
|
64
65
|
f"🔍 View metrics for your job via "
|
|
65
66
|
f"[cyan]'truss train metrics --job-id {job_id}'[/cyan]\n"
|
|
66
67
|
f"{cache_summary_snippet}"
|
|
67
|
-
f"🌐
|
|
68
|
+
f"🌐 View job in the UI: {common.format_link(core.status_page_url(remote_provider.remote_url, project_id, job_id))}"
|
|
68
69
|
)
|
|
69
70
|
|
|
70
71
|
|
|
@@ -80,8 +81,13 @@ def _handle_post_create_logic(
|
|
|
80
81
|
style="green",
|
|
81
82
|
)
|
|
82
83
|
else:
|
|
84
|
+
# recreate currently doesn't pass back a job object.
|
|
83
85
|
_print_training_job_success_message(
|
|
84
|
-
job_id,
|
|
86
|
+
job_id,
|
|
87
|
+
project_id,
|
|
88
|
+
project_name,
|
|
89
|
+
job_resp.get("job_object"),
|
|
90
|
+
remote_provider,
|
|
85
91
|
)
|
|
86
92
|
|
|
87
93
|
if tail:
|
|
@@ -156,11 +162,16 @@ def recreate_training_job(job_id: Optional[str], remote: Optional[str], tail: bo
|
|
|
156
162
|
@train.command(name="logs")
|
|
157
163
|
@click.option("--remote", type=str, required=False, help="Remote to use")
|
|
158
164
|
@click.option("--project-id", type=str, required=False, help="Project ID.")
|
|
165
|
+
@click.option("--project", type=str, required=False, help="Project name or project id.")
|
|
159
166
|
@click.option("--job-id", type=str, required=False, help="Job ID.")
|
|
160
167
|
@click.option("--tail", is_flag=True, help="Tail for ongoing logs.")
|
|
161
168
|
@common.common_options()
|
|
162
169
|
def get_job_logs(
|
|
163
|
-
remote: Optional[str],
|
|
170
|
+
remote: Optional[str],
|
|
171
|
+
project_id: Optional[str],
|
|
172
|
+
project: Optional[str],
|
|
173
|
+
job_id: Optional[str],
|
|
174
|
+
tail: bool,
|
|
164
175
|
):
|
|
165
176
|
"""Fetch logs for a training job"""
|
|
166
177
|
|
|
@@ -170,6 +181,10 @@ def get_job_logs(
|
|
|
170
181
|
remote_provider: BasetenRemote = cast(
|
|
171
182
|
BasetenRemote, RemoteFactory.create(remote=remote)
|
|
172
183
|
)
|
|
184
|
+
project_id = _maybe_resolve_project_id_from_id_or_name(
|
|
185
|
+
remote_provider, project_id=project_id, project=project
|
|
186
|
+
)
|
|
187
|
+
|
|
173
188
|
project_id, job_id = train_common.get_most_recent_job(
|
|
174
189
|
remote_provider, project_id, job_id
|
|
175
190
|
)
|
|
@@ -188,12 +203,17 @@ def get_job_logs(
|
|
|
188
203
|
|
|
189
204
|
@train.command(name="stop")
|
|
190
205
|
@click.option("--project-id", type=str, required=False, help="Project ID.")
|
|
206
|
+
@click.option("--project", type=str, required=False, help="Project name or project id.")
|
|
191
207
|
@click.option("--job-id", type=str, required=False, help="Job ID.")
|
|
192
208
|
@click.option("--all", is_flag=True, help="Stop all running jobs.")
|
|
193
209
|
@click.option("--remote", type=str, required=False, help="Remote to use")
|
|
194
210
|
@common.common_options()
|
|
195
211
|
def stop_job(
|
|
196
|
-
project_id: Optional[str],
|
|
212
|
+
project_id: Optional[str],
|
|
213
|
+
project: Optional[str],
|
|
214
|
+
job_id: Optional[str],
|
|
215
|
+
all: bool,
|
|
216
|
+
remote: Optional[str],
|
|
197
217
|
):
|
|
198
218
|
"""Stop a training job"""
|
|
199
219
|
|
|
@@ -203,6 +223,9 @@ def stop_job(
|
|
|
203
223
|
remote_provider: BasetenRemote = cast(
|
|
204
224
|
BasetenRemote, RemoteFactory.create(remote=remote)
|
|
205
225
|
)
|
|
226
|
+
project_id = _maybe_resolve_project_id_from_id_or_name(
|
|
227
|
+
remote_provider, project_id=project_id, project=project
|
|
228
|
+
)
|
|
206
229
|
if all:
|
|
207
230
|
train_cli.stop_all_jobs(remote_provider, project_id)
|
|
208
231
|
else:
|
|
@@ -217,13 +240,17 @@ def stop_job(
|
|
|
217
240
|
@click.option(
|
|
218
241
|
"--project-id", type=str, required=False, help="View training jobs for a project."
|
|
219
242
|
)
|
|
243
|
+
@click.option("--project", type=str, required=False, help="Project name or project id.")
|
|
220
244
|
@click.option(
|
|
221
245
|
"--job-id", type=str, required=False, help="View a specific training job."
|
|
222
246
|
)
|
|
223
247
|
@click.option("--remote", type=str, required=False, help="Remote to use")
|
|
224
248
|
@common.common_options()
|
|
225
249
|
def view_training(
|
|
226
|
-
project_id: Optional[str],
|
|
250
|
+
project_id: Optional[str],
|
|
251
|
+
project: Optional[str],
|
|
252
|
+
job_id: Optional[str],
|
|
253
|
+
remote: Optional[str],
|
|
227
254
|
):
|
|
228
255
|
"""List all training jobs for a project"""
|
|
229
256
|
|
|
@@ -233,16 +260,24 @@ def view_training(
|
|
|
233
260
|
remote_provider: BasetenRemote = cast(
|
|
234
261
|
BasetenRemote, RemoteFactory.create(remote=remote)
|
|
235
262
|
)
|
|
263
|
+
project_id = _maybe_resolve_project_id_from_id_or_name(
|
|
264
|
+
remote_provider, project_id=project_id, project=project
|
|
265
|
+
)
|
|
266
|
+
|
|
236
267
|
train_cli.view_training_details(remote_provider, project_id, job_id)
|
|
237
268
|
|
|
238
269
|
|
|
239
270
|
@train.command(name="metrics")
|
|
240
271
|
@click.option("--project-id", type=str, required=False, help="Project ID.")
|
|
272
|
+
@click.option("--project", type=str, required=False, help="Project name or project id.")
|
|
241
273
|
@click.option("--job-id", type=str, required=False, help="Job ID.")
|
|
242
274
|
@click.option("--remote", type=str, required=False, help="Remote to use")
|
|
243
275
|
@common.common_options()
|
|
244
276
|
def get_job_metrics(
|
|
245
|
-
project_id: Optional[str],
|
|
277
|
+
project_id: Optional[str],
|
|
278
|
+
project: Optional[str],
|
|
279
|
+
job_id: Optional[str],
|
|
280
|
+
remote: Optional[str],
|
|
246
281
|
):
|
|
247
282
|
"""Get metrics for a training job"""
|
|
248
283
|
|
|
@@ -252,11 +287,15 @@ def get_job_metrics(
|
|
|
252
287
|
remote_provider: BasetenRemote = cast(
|
|
253
288
|
BasetenRemote, RemoteFactory.create(remote=remote)
|
|
254
289
|
)
|
|
290
|
+
project_id = _maybe_resolve_project_id_from_id_or_name(
|
|
291
|
+
remote_provider, project_id=project_id, project=project
|
|
292
|
+
)
|
|
255
293
|
train_cli.view_training_job_metrics(remote_provider, project_id, job_id)
|
|
256
294
|
|
|
257
295
|
|
|
258
296
|
@train.command(name="deploy_checkpoints")
|
|
259
297
|
@click.option("--project-id", type=str, required=False, help="Project ID.")
|
|
298
|
+
@click.option("--project", type=str, required=False, help="Project name or project id.")
|
|
260
299
|
@click.option("--job-id", type=str, required=False, help="Job ID.")
|
|
261
300
|
@click.option(
|
|
262
301
|
"--config",
|
|
@@ -271,6 +310,7 @@ def get_job_metrics(
|
|
|
271
310
|
@common.common_options()
|
|
272
311
|
def deploy_checkpoints(
|
|
273
312
|
project_id: Optional[str],
|
|
313
|
+
project: Optional[str],
|
|
274
314
|
job_id: Optional[str],
|
|
275
315
|
config: Optional[str],
|
|
276
316
|
remote: Optional[str],
|
|
@@ -286,6 +326,9 @@ def deploy_checkpoints(
|
|
|
286
326
|
remote_provider: BasetenRemote = cast(
|
|
287
327
|
BasetenRemote, RemoteFactory.create(remote=remote)
|
|
288
328
|
)
|
|
329
|
+
project_id = _maybe_resolve_project_id_from_id_or_name(
|
|
330
|
+
remote_provider, project_id=project_id, project=project
|
|
331
|
+
)
|
|
289
332
|
prepare_checkpoint_result = train_cli.prepare_checkpoint_deploy(
|
|
290
333
|
remote_provider,
|
|
291
334
|
train_cli.PrepareCheckpointArgs(
|
|
@@ -492,3 +535,15 @@ def view_cache_summary(project: str, remote: Optional[str], sort: str, order: st
|
|
|
492
535
|
)
|
|
493
536
|
|
|
494
537
|
train_cli.view_cache_summary_by_project(remote_provider, project, sort, order)
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
def _maybe_resolve_project_id_from_id_or_name(
|
|
541
|
+
remote_provider: BasetenRemote, project_id: Optional[str], project: Optional[str]
|
|
542
|
+
) -> Optional[str]:
|
|
543
|
+
"""resolve the project_id or project. `project` can be name or id"""
|
|
544
|
+
if project and project_id:
|
|
545
|
+
console.print("Both `project-id` and `project` provided. Using `project`.")
|
|
546
|
+
project_str = project or project_id
|
|
547
|
+
if not project_str:
|
|
548
|
+
return None
|
|
549
|
+
return train_cli.fetch_project_by_name_or_id(remote_provider, project_str)["id"]
|
|
@@ -33,7 +33,7 @@ RUN useradd -u {{ app_user_uid }} -ms /bin/bash {{ app_username }}
|
|
|
33
33
|
ENV DEBIAN_FRONTEND=noninteractive
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
{%- set UV_VERSION = "0.
|
|
36
|
+
{%- set UV_VERSION = "0.8.22" %}
|
|
37
37
|
{#
|
|
38
38
|
NB(nikhil): We use a semi-complex uv installation command across the board:
|
|
39
39
|
- A generous UV_HTTP_TIMEOUT (5m) for packages that take a long time to install.
|
|
@@ -59,10 +59,12 @@ RUN {{ python_exec_path }} -c "import sys; \
|
|
|
59
59
|
{% endblock %}
|
|
60
60
|
|
|
61
61
|
{% block install_uv %}
|
|
62
|
-
{# Install `uv` and `curl` if not already present in the image.
|
|
62
|
+
{# Install `uv` and `curl` if not already present in the image. We validate the expected location for `uv` at the very end
|
|
63
|
+
due to limitations with `pipefail` in Docker context. #}
|
|
63
64
|
RUN if ! command -v uv >/dev/null 2>&1; then \
|
|
64
65
|
command -v curl >/dev/null 2>&1 || (apt update && apt install -y curl) && \
|
|
65
|
-
curl -LsSf --retry 5 --retry-delay 5 https://astral.sh/uv/{{ UV_VERSION }}/install.sh | sh
|
|
66
|
+
curl -LsSf --retry 5 --retry-delay 5 https://astral.sh/uv/{{ UV_VERSION }}/install.sh | sh && \
|
|
67
|
+
test -x ${HOME}/.local/bin/uv; \
|
|
66
68
|
fi
|
|
67
69
|
{# Add the user's local bin to the path, used by uv. #}
|
|
68
70
|
ENV PATH=${PATH}:${HOME}/.local/bin
|
|
@@ -17,7 +17,8 @@ RUN /usr/local/bin/python3 -c "import sys; \
|
|
|
17
17
|
|| { echo "ERROR: Supplied base image does not have 3.8 <= python <= 3.13"; exit 1; }
|
|
18
18
|
RUN if ! command -v uv >/dev/null 2>&1; then \
|
|
19
19
|
command -v curl >/dev/null 2>&1 || (apt update && apt install -y curl) && \
|
|
20
|
-
curl -LsSf --retry 5 --retry-delay 5 https://astral.sh/uv/0.
|
|
20
|
+
curl -LsSf --retry 5 --retry-delay 5 https://astral.sh/uv/0.8.22/install.sh | sh && \
|
|
21
|
+
test -x ${HOME}/.local/bin/uv; \
|
|
21
22
|
fi
|
|
22
23
|
ENV PATH=${PATH}:${HOME}/.local/bin
|
|
23
24
|
ENV PYTHONUNBUFFERED="True"
|
|
@@ -11,13 +11,13 @@ truss/base/truss_spec.py,sha256=jFVF79CXoEEspl2kXBAPyi-rwISReIGTdobGpaIhwJw,5979
|
|
|
11
11
|
truss/cli/chains_commands.py,sha256=Kpa5mCg6URAJQE2ZmZfVQFhjBHEitKT28tKiW0H6XAI,17406
|
|
12
12
|
truss/cli/cli.py,sha256=PaMkuwXZflkU7sa1tEoT_Zmy-iBkEZs1m4IVqcieaeo,30367
|
|
13
13
|
truss/cli/remote_cli.py,sha256=G_xCKRXzgkCmkiZJhUFfsv5YSVgde1jLA5LPQitpZgI,1905
|
|
14
|
-
truss/cli/train_commands.py,sha256=
|
|
14
|
+
truss/cli/train_commands.py,sha256=sJN_Qpq-ejHY7KZ555n37PzpYEF-gZiQCVHW5JwUPHo,19303
|
|
15
15
|
truss/cli/logs/base_watcher.py,sha256=KKyd7lIrdaEeDVt8EtjMioSPGVpLyOcF0ewyzE_GGdQ,2785
|
|
16
16
|
truss/cli/logs/model_log_watcher.py,sha256=NACcP-wkcaroYa2Cb9BZC7Yr0554WZa_FSM2LXOf4A8,1263
|
|
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
|
|
20
|
-
truss/cli/train/core.py,sha256=
|
|
20
|
+
truss/cli/train/core.py,sha256=cqE0iBEElqP3oMDpCimuwpCwFyqfOYEBhweCZat7GiI,26262
|
|
21
21
|
truss/cli/train/deploy_from_checkpoint_config.yml,sha256=mktaVrfhN8Kjx1UveC4xr-gTW-kjwbHvq6bx_LpO-Wg,371
|
|
22
22
|
truss/cli/train/deploy_from_checkpoint_config_whisper.yml,sha256=6GbOorYC8ml0UyOUvuBpFO_fuYtYE646JqsalR-D4oY,406
|
|
23
23
|
truss/cli/train/metrics_watcher.py,sha256=smz-zrEsBj_-wJHI0pAZ-EAPrvfCWzq1eQjGiFNM-Mk,12755
|
|
@@ -66,7 +66,7 @@ truss/remote/baseten/utils/time.py,sha256=Ry9GMjYnbIGYVIGwtmv4V8ljWjvdcaCf5NOQzl
|
|
|
66
66
|
truss/remote/baseten/utils/transfer.py,sha256=d3VptuQb6M1nyS6kz0BAfeOYDLkMKUjatJXpY-mp-As,1548
|
|
67
67
|
truss/templates/README.md.jinja,sha256=N7CJdyldZuJamj5jLh47le0hFBdu9irVsTBqoxhPNPQ,2476
|
|
68
68
|
truss/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
69
|
-
truss/templates/base.Dockerfile.jinja,sha256=
|
|
69
|
+
truss/templates/base.Dockerfile.jinja,sha256=DgvNqmkt5QRrqy7a9hw6HffmVTUrdGl06oVZ4eeha5Y,5253
|
|
70
70
|
truss/templates/cache.Dockerfile.jinja,sha256=1qZqDo1phrcqi-Vwol-VafYJkADsBbQWU6huQ-_1x00,1146
|
|
71
71
|
truss/templates/cache_requirements.txt,sha256=xoPoJ-OVnf1z6oq_RVM3vCr3ionByyqMLj7wGs61nUs,87
|
|
72
72
|
truss/templates/copy_cache_files.Dockerfile.jinja,sha256=Os5zFdYLZ_AfCRGq4RcpVTObOTwL7zvmwYcvOzd_Zqo,126
|
|
@@ -184,7 +184,7 @@ truss/tests/test_data/pima-indians-diabetes.csv,sha256=BvW3ws17ymhv2k-S6rX2Hn_2Q
|
|
|
184
184
|
truss/tests/test_data/readme_int_example.md,sha256=fuHvpLtdkJy1f4NAR_djotVBdzusHYNXc-Fwh588XAE,1586
|
|
185
185
|
truss/tests/test_data/readme_no_example.md,sha256=T2CzFMRvICXeX3_5XbFoqhHchcHGot-xM7izx34B3aQ,1607
|
|
186
186
|
truss/tests/test_data/readme_str_example.md,sha256=fP4pvMqgLdIapaOf_BgRiV0H7pw4so0RNxrlq5lbROE,1726
|
|
187
|
-
truss/tests/test_data/server.Dockerfile,sha256=
|
|
187
|
+
truss/tests/test_data/server.Dockerfile,sha256=3rWiU3RxBh0PIh8pS23FnP8UA-ErmzxTlgf_J22mMQ8,2024
|
|
188
188
|
truss/tests/test_data/annotated_types_truss/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
189
189
|
truss/tests/test_data/annotated_types_truss/config.yaml,sha256=B-ZyyjLLqtxGfXj2tkH68Hy7NOMB_coYvoWyWom61g0,147
|
|
190
190
|
truss/tests/test_data/annotated_types_truss/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -368,8 +368,8 @@ truss_train/deployment.py,sha256=lWWANSuzBWu2M4oK4qD7n-oVR1JKdmw2Pn5BJQHg-Ck,307
|
|
|
368
368
|
truss_train/loader.py,sha256=0o66EjBaHc2YY4syxxHVR4ordJWs13lNXnKjKq2wq0U,1630
|
|
369
369
|
truss_train/public_api.py,sha256=9N_NstiUlmBuLUwH_fNG_1x7OhGCytZLNvqKXBlStrM,1220
|
|
370
370
|
truss_train/restore_from_checkpoint.py,sha256=8hdPm-WSgkt74HDPjvCjZMBpvA9MwtoYsxVjOoa7BaM,1176
|
|
371
|
-
truss-0.11.
|
|
372
|
-
truss-0.11.
|
|
373
|
-
truss-0.11.
|
|
374
|
-
truss-0.11.
|
|
375
|
-
truss-0.11.
|
|
371
|
+
truss-0.11.8rc3.dist-info/METADATA,sha256=ziFdl3TpygMkpZIMoHXADHO9gSIBCXaVeGdXelt46U0,6680
|
|
372
|
+
truss-0.11.8rc3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
373
|
+
truss-0.11.8rc3.dist-info/entry_points.txt,sha256=-MwKfHHQHQ6j0HqIgvxrz3CehCmczDLTD-OsRHnjjuU,130
|
|
374
|
+
truss-0.11.8rc3.dist-info/licenses/LICENSE,sha256=FTqGzu85i-uw1Gi8E_o0oD60bH9yQ_XIGtZbA1QUYiw,1064
|
|
375
|
+
truss-0.11.8rc3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|