trap-cli 0.0.7__tar.gz → 0.0.8__tar.gz
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.
- {trap_cli-0.0.7 → trap_cli-0.0.8}/PKG-INFO +1 -1
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/_version.py +2 -2
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/cli/__init__.py +29 -23
- trap_cli-0.0.8/src/trap/display/__init__.py +19 -0
- trap_cli-0.0.7/src/trap/report/rich.py → trap_cli-0.0.8/src/trap/display/report.py +23 -1
- trap_cli-0.0.7/src/trap/display/__init__.py +0 -4
- trap_cli-0.0.7/src/trap/report/__init__.py +0 -18
- trap_cli-0.0.7/src/trap/report/base.py +0 -8
- trap_cli-0.0.7/src/trap/report/json.py +0 -11
- {trap_cli-0.0.7 → trap_cli-0.0.8}/.gitignore +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/LICENSE +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/README.md +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/examples/echo/task/README.md +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/pyproject.toml +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/__init__.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/auth/__init__.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/auth/client.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/auth/login.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/auth/oauth.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/auth/store.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/cli/_auth.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/cli/_console.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/cost/__init__.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/cost/calculator.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/cost/providers.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/cost/proxy.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/display/progress.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/display/submit.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/environment/__init__.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/environment/detector.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/git_ops/__init__.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/git_ops/base.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/git_ops/local.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/git_ops/remote.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/git_ops/rev.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/git_ops/url.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/loader/__init__.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/loader/errors.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/loader/trap_yaml.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/loader/traptask_yaml.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/models/__init__.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/models/cost.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/models/environment.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/models/provenance.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/models/report.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/models/results.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/models/trap_yaml.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/models/traptask_yaml.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/runner/__init__.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/runner/capture.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/runner/grader.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/runner/judge.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/runner/layout.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/runner/proc.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/runner/solution.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/runner/task.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/workspace/__init__.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/workspace/identity.py +0 -0
- {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/workspace/store.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: trap-cli
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.8
|
|
4
4
|
Summary: tp — non-invasive CLI testing framework for AI workflows. Submits results to trapstreet.run.
|
|
5
5
|
Project-URL: Homepage, https://trapstreet.run
|
|
6
6
|
Project-URL: Repository, https://github.com/trapstreet/trap
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.0.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 0,
|
|
21
|
+
__version__ = version = '0.0.8'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 0, 8)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -13,12 +13,11 @@ from trap import __version__
|
|
|
13
13
|
from trap.auth import DEFAULT_SERVER, ApiClient, ApiError, AuthStore
|
|
14
14
|
from trap.cli._auth import auth_app
|
|
15
15
|
from trap.cli._console import _die, _env_truthy, console, err_console
|
|
16
|
-
from trap.display import CaseProgress, render_submit_result
|
|
16
|
+
from trap.display import CaseProgress, OutputFormat, render_submit_result, renderer_factory
|
|
17
17
|
from trap.environment import EnvironmentDetector
|
|
18
18
|
from trap.git_ops import GitOpsError, LocalRepo, ParsedGitUrl
|
|
19
19
|
from trap.loader import ConfigError, TrapLoader, TraptaskLoader
|
|
20
20
|
from trap.models import Provenance, ReportData
|
|
21
|
-
from trap.report import OutputFormat, renderer_factory
|
|
22
21
|
from trap.runner import TaskRunner
|
|
23
22
|
from trap.workspace import SolutionIdentity, Workspace
|
|
24
23
|
|
|
@@ -50,13 +49,13 @@ def _main(
|
|
|
50
49
|
def _no_report(workspace: Workspace, error: FileNotFoundError) -> typer.Exit:
|
|
51
50
|
"""Exit for a report miss, with advice matching the likely cause: an empty
|
|
52
51
|
workspace means the user never ran; existing runs under *other* solution keys
|
|
53
|
-
mean a cwd /
|
|
52
|
+
mean a cwd / SOLUTION mismatch, where re-running would just miss again."""
|
|
54
53
|
msg = str(error)
|
|
55
54
|
if keys := workspace.solution_keys():
|
|
56
55
|
msg += (
|
|
57
56
|
"\nsolutions with runs in this workspace: "
|
|
58
57
|
+ ", ".join(keys)
|
|
59
|
-
+ "\ncheck that
|
|
58
|
+
+ "\ncheck that SOLUTION (and the cwd) match the ones used for [bold]tp run[/bold]"
|
|
60
59
|
)
|
|
61
60
|
else:
|
|
62
61
|
msg += ". Run [bold]tp run[/bold] first."
|
|
@@ -120,14 +119,19 @@ def _confirm_unanchored(provenance: Provenance, *, allow: bool) -> None:
|
|
|
120
119
|
|
|
121
120
|
@app.command()
|
|
122
121
|
def run(
|
|
123
|
-
task: Annotated[str | None, typer.Argument()] = None,
|
|
124
122
|
solution: Annotated[
|
|
125
123
|
str | None,
|
|
126
|
-
typer.
|
|
124
|
+
typer.Argument(help="Solution to run: a local path or a git+ URL (default: cwd)."),
|
|
127
125
|
] = None,
|
|
126
|
+
task: Annotated[
|
|
127
|
+
str | None,
|
|
128
|
+
typer.Option("--task", help="Task alias from trap.yaml (default: the first task)."),
|
|
129
|
+
] = None,
|
|
130
|
+
workspace: Annotated[Path, typer.Option("--workspace", "-w")] = Path(Workspace.DEFAULT_DIRNAME),
|
|
131
|
+
output: Annotated[OutputFormat, typer.Option("--output", "-o")] = OutputFormat.rich,
|
|
128
132
|
clone_to: Annotated[
|
|
129
133
|
Path | None,
|
|
130
|
-
typer.Option("--clone-to", help="Where to clone a git+ URL
|
|
134
|
+
typer.Option("--clone-to", help="Where to clone a git+ URL SOLUTION (default: ./<repo>)."),
|
|
131
135
|
] = None,
|
|
132
136
|
trust_remote: Annotated[
|
|
133
137
|
bool,
|
|
@@ -146,7 +150,6 @@ def run(
|
|
|
146
150
|
),
|
|
147
151
|
] = False,
|
|
148
152
|
tags: Annotated[list[str] | None, typer.Option("--tag", "-t")] = None,
|
|
149
|
-
output: Annotated[OutputFormat, typer.Option("--output", "-o")] = OutputFormat.rich,
|
|
150
153
|
fail_fast: Annotated[bool, typer.Option("--fail-fast")] = False,
|
|
151
154
|
setup_solution: Annotated[
|
|
152
155
|
bool,
|
|
@@ -162,7 +165,6 @@ def run(
|
|
|
162
165
|
help="Force-run the task's setup_cmd even when no remote pull brought new code.",
|
|
163
166
|
),
|
|
164
167
|
] = False,
|
|
165
|
-
workspace: Annotated[Path, typer.Option("--workspace", "-w")] = Path(Workspace.DEFAULT_DIRNAME),
|
|
166
168
|
environment: Annotated[
|
|
167
169
|
bool,
|
|
168
170
|
typer.Option(
|
|
@@ -180,11 +182,11 @@ def run(
|
|
|
180
182
|
) -> None:
|
|
181
183
|
"""Run a task against a solution.
|
|
182
184
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
+
SOLUTION is a local path, or a git+ URL to clone into ./<repo> (or
|
|
186
|
+
--clone-to). Omit it to use the trap.yaml in the cwd.
|
|
185
187
|
"""
|
|
186
188
|
# Gate trap's auto-download-and-run of any remote source before it happens — once
|
|
187
|
-
# for a remote
|
|
189
|
+
# for a remote SOLUTION, once for a remote task source (resolved from trap.yaml).
|
|
188
190
|
trust = trust_remote or _env_truthy("TRAP_TRUST_REMOTE")
|
|
189
191
|
if solution is not None and ParsedGitUrl.looks_remote(solution):
|
|
190
192
|
_confirm_remote(solution, trust=trust)
|
|
@@ -271,14 +273,17 @@ def run(
|
|
|
271
273
|
|
|
272
274
|
@app.command()
|
|
273
275
|
def report(
|
|
274
|
-
task: Annotated[str | None, typer.Argument()] = None,
|
|
275
|
-
run: Annotated[str, typer.Argument()] = "latest",
|
|
276
276
|
solution: Annotated[
|
|
277
277
|
str | None,
|
|
278
|
-
typer.
|
|
278
|
+
typer.Argument(help="Local solution path holding trap.yaml (default: cwd)."),
|
|
279
279
|
] = None,
|
|
280
|
-
|
|
280
|
+
task: Annotated[
|
|
281
|
+
str | None,
|
|
282
|
+
typer.Option("--task", help="Task alias from trap.yaml (default: the first task)."),
|
|
283
|
+
] = None,
|
|
284
|
+
run: Annotated[str, typer.Option("--run", "-r", help="Which run to display.")] = "latest",
|
|
281
285
|
workspace: Annotated[Path, typer.Option("--workspace", "-w")] = Path(Workspace.DEFAULT_DIRNAME),
|
|
286
|
+
output: Annotated[OutputFormat, typer.Option("--output", "-o")] = OutputFormat.rich,
|
|
282
287
|
) -> None:
|
|
283
288
|
"""Display a report for a task (defaults to latest run)."""
|
|
284
289
|
try:
|
|
@@ -295,19 +300,20 @@ def report(
|
|
|
295
300
|
|
|
296
301
|
@app.command()
|
|
297
302
|
def submit(
|
|
303
|
+
solution: Annotated[
|
|
304
|
+
str | None,
|
|
305
|
+
typer.Argument(help="Local solution path holding trap.yaml (default: cwd)."),
|
|
306
|
+
] = None,
|
|
298
307
|
task: Annotated[
|
|
299
308
|
str | None,
|
|
300
|
-
typer.
|
|
301
|
-
|
|
309
|
+
typer.Option(
|
|
310
|
+
"--task",
|
|
311
|
+
help="Task alias from trap.yaml (default: the first task). "
|
|
302
312
|
"Used as both the local run dir and the trapstreet task_id.",
|
|
303
313
|
),
|
|
304
314
|
] = None,
|
|
305
|
-
solution: Annotated[
|
|
306
|
-
str | None,
|
|
307
|
-
typer.Option("--solution", help="Local solution path holding trap.yaml (default: cwd)."),
|
|
308
|
-
] = None,
|
|
309
|
-
workspace: Annotated[Path, typer.Option("--workspace", "-w")] = Path(Workspace.DEFAULT_DIRNAME),
|
|
310
315
|
run: Annotated[str, typer.Option("--run", "-r", help="Which run to upload.")] = "latest",
|
|
316
|
+
workspace: Annotated[Path, typer.Option("--workspace", "-w")] = Path(Workspace.DEFAULT_DIRNAME),
|
|
311
317
|
allow_unanchored: Annotated[
|
|
312
318
|
bool,
|
|
313
319
|
typer.Option(
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from trap.display.progress import CaseProgress
|
|
2
|
+
from trap.display.report import (
|
|
3
|
+
BaseRenderer,
|
|
4
|
+
JsonRenderer,
|
|
5
|
+
OutputFormat,
|
|
6
|
+
RichRenderer,
|
|
7
|
+
renderer_factory,
|
|
8
|
+
)
|
|
9
|
+
from trap.display.submit import render_submit_result
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"BaseRenderer",
|
|
13
|
+
"CaseProgress",
|
|
14
|
+
"JsonRenderer",
|
|
15
|
+
"OutputFormat",
|
|
16
|
+
"RichRenderer",
|
|
17
|
+
"render_submit_result",
|
|
18
|
+
"renderer_factory",
|
|
19
|
+
]
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
"""Report renderers: turn a ReportData into terminal output (rich table or JSON)."""
|
|
2
|
+
|
|
1
3
|
from __future__ import annotations
|
|
2
4
|
|
|
5
|
+
import enum
|
|
3
6
|
import json
|
|
7
|
+
import sys
|
|
4
8
|
|
|
5
9
|
from rich import box
|
|
6
10
|
from rich.console import Console
|
|
@@ -10,7 +14,21 @@ from rich.table import Table
|
|
|
10
14
|
from rich.text import Text
|
|
11
15
|
|
|
12
16
|
from trap.models import CaseResult, ReportData
|
|
13
|
-
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class OutputFormat(enum.StrEnum):
|
|
20
|
+
rich = "rich"
|
|
21
|
+
json = "json"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class BaseRenderer:
|
|
25
|
+
def render(self, data: ReportData) -> None:
|
|
26
|
+
raise NotImplementedError
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class JsonRenderer(BaseRenderer):
|
|
30
|
+
def render(self, data: ReportData) -> None:
|
|
31
|
+
sys.stdout.write(data.model_dump_json(indent=2) + "\n")
|
|
14
32
|
|
|
15
33
|
|
|
16
34
|
class RichRenderer(BaseRenderer):
|
|
@@ -114,3 +132,7 @@ class RichRenderer(BaseRenderer):
|
|
|
114
132
|
def render(self, data: ReportData) -> None:
|
|
115
133
|
self.console.print(self._build_summary(data))
|
|
116
134
|
self.console.print(self._build_table(data))
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def renderer_factory(fmt: OutputFormat) -> BaseRenderer:
|
|
138
|
+
return {OutputFormat.rich: RichRenderer, OutputFormat.json: JsonRenderer}[fmt]()
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import enum
|
|
4
|
-
|
|
5
|
-
from trap.report.base import BaseRenderer
|
|
6
|
-
from trap.report.json import JsonRenderer
|
|
7
|
-
from trap.report.rich import RichRenderer
|
|
8
|
-
|
|
9
|
-
__all__ = ["BaseRenderer", "JsonRenderer", "OutputFormat", "RichRenderer", "renderer_factory"]
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class OutputFormat(enum.StrEnum):
|
|
13
|
-
rich = "rich"
|
|
14
|
-
json = "json"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def renderer_factory(fmt: OutputFormat) -> BaseRenderer:
|
|
18
|
-
return {OutputFormat.rich: RichRenderer, OutputFormat.json: JsonRenderer}[fmt]()
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import sys
|
|
4
|
-
|
|
5
|
-
from trap.models import ReportData
|
|
6
|
-
from trap.report.base import BaseRenderer
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class JsonRenderer(BaseRenderer):
|
|
10
|
-
def render(self, data: ReportData) -> None:
|
|
11
|
-
sys.stdout.write(data.model_dump_json(indent=2) + "\n")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|