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.
Files changed (59) hide show
  1. {trap_cli-0.0.7 → trap_cli-0.0.8}/PKG-INFO +1 -1
  2. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/_version.py +2 -2
  3. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/cli/__init__.py +29 -23
  4. trap_cli-0.0.8/src/trap/display/__init__.py +19 -0
  5. trap_cli-0.0.7/src/trap/report/rich.py → trap_cli-0.0.8/src/trap/display/report.py +23 -1
  6. trap_cli-0.0.7/src/trap/display/__init__.py +0 -4
  7. trap_cli-0.0.7/src/trap/report/__init__.py +0 -18
  8. trap_cli-0.0.7/src/trap/report/base.py +0 -8
  9. trap_cli-0.0.7/src/trap/report/json.py +0 -11
  10. {trap_cli-0.0.7 → trap_cli-0.0.8}/.gitignore +0 -0
  11. {trap_cli-0.0.7 → trap_cli-0.0.8}/LICENSE +0 -0
  12. {trap_cli-0.0.7 → trap_cli-0.0.8}/README.md +0 -0
  13. {trap_cli-0.0.7 → trap_cli-0.0.8}/examples/echo/task/README.md +0 -0
  14. {trap_cli-0.0.7 → trap_cli-0.0.8}/pyproject.toml +0 -0
  15. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/__init__.py +0 -0
  16. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/auth/__init__.py +0 -0
  17. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/auth/client.py +0 -0
  18. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/auth/login.py +0 -0
  19. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/auth/oauth.py +0 -0
  20. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/auth/store.py +0 -0
  21. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/cli/_auth.py +0 -0
  22. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/cli/_console.py +0 -0
  23. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/cost/__init__.py +0 -0
  24. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/cost/calculator.py +0 -0
  25. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/cost/providers.py +0 -0
  26. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/cost/proxy.py +0 -0
  27. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/display/progress.py +0 -0
  28. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/display/submit.py +0 -0
  29. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/environment/__init__.py +0 -0
  30. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/environment/detector.py +0 -0
  31. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/git_ops/__init__.py +0 -0
  32. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/git_ops/base.py +0 -0
  33. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/git_ops/local.py +0 -0
  34. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/git_ops/remote.py +0 -0
  35. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/git_ops/rev.py +0 -0
  36. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/git_ops/url.py +0 -0
  37. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/loader/__init__.py +0 -0
  38. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/loader/errors.py +0 -0
  39. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/loader/trap_yaml.py +0 -0
  40. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/loader/traptask_yaml.py +0 -0
  41. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/models/__init__.py +0 -0
  42. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/models/cost.py +0 -0
  43. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/models/environment.py +0 -0
  44. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/models/provenance.py +0 -0
  45. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/models/report.py +0 -0
  46. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/models/results.py +0 -0
  47. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/models/trap_yaml.py +0 -0
  48. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/models/traptask_yaml.py +0 -0
  49. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/runner/__init__.py +0 -0
  50. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/runner/capture.py +0 -0
  51. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/runner/grader.py +0 -0
  52. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/runner/judge.py +0 -0
  53. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/runner/layout.py +0 -0
  54. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/runner/proc.py +0 -0
  55. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/runner/solution.py +0 -0
  56. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/runner/task.py +0 -0
  57. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/workspace/__init__.py +0 -0
  58. {trap_cli-0.0.7 → trap_cli-0.0.8}/src/trap/workspace/identity.py +0 -0
  59. {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.7
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.7'
22
- __version_tuple__ = version_tuple = (0, 0, 7)
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 / --solution mismatch, where re-running would just miss again."""
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 --solution (and the cwd) match the ones used for [bold]tp run[/bold]"
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.Option("--solution", help="Solution to run: a local path or a git+ URL (default: cwd)."),
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 --solution (default: ./<repo>)."),
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
- --solution is the solution to run: a local path, or a git+ URL to clone
184
- into ./<repo> (or --clone-to). Omit it to use the trap.yaml in the cwd.
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 --solution, once for a remote task source (resolved from trap.yaml).
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.Option("--solution", help="Local solution path holding trap.yaml (default: cwd)."),
278
+ typer.Argument(help="Local solution path holding trap.yaml (default: cwd)."),
279
279
  ] = None,
280
- output: Annotated[OutputFormat, typer.Option("--output", "-o")] = OutputFormat.rich,
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.Argument(
301
- help="Task name (defaults to first task in trap.yaml). "
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
- from trap.report.base import BaseRenderer
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,4 +0,0 @@
1
- from trap.display.progress import CaseProgress
2
- from trap.display.submit import render_submit_result
3
-
4
- __all__ = ["CaseProgress", "render_submit_result"]
@@ -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,8 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from trap.models import ReportData
4
-
5
-
6
- class BaseRenderer:
7
- def render(self, data: ReportData) -> None:
8
- raise NotImplementedError
@@ -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