reeval-python 0.15.1__tar.gz → 0.16.1__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.
- {reeval_python-0.15.1 → reeval_python-0.16.1}/PKG-INFO +26 -10
- {reeval_python-0.15.1 → reeval_python-0.16.1}/README.md +25 -9
- {reeval_python-0.15.1 → reeval_python-0.16.1}/pyproject.toml +1 -1
- {reeval_python-0.15.1 → reeval_python-0.16.1}/src/reeval_python/__init__.py +3 -3
- {reeval_python-0.15.1 → reeval_python-0.16.1}/src/reeval_python/_wire.py +135 -113
- {reeval_python-0.15.1 → reeval_python-0.16.1}/src/reeval_python/aio.py +1 -9
- reeval_python-0.16.1/src/reeval_python/binaries.json +55 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/src/reeval_python/checks.py +8 -1
- {reeval_python-0.15.1 → reeval_python-0.16.1}/src/reeval_python/context.py +39 -7
- {reeval_python-0.15.1 → reeval_python-0.16.1}/src/reeval_python/expect.py +51 -23
- {reeval_python-0.15.1 → reeval_python-0.16.1}/src/reeval_python/options.py +34 -5
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/context/expect-fail.eval.py +1 -1
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/context/expect-fail.sync.eval.py +1 -1
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/context/expect.eval.py +2 -1
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/context/expect.sync.eval.py +2 -1
- reeval_python-0.16.1/tests/context/judge.eval.py +14 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/context/judge.sync.eval.py +3 -3
- reeval_python-0.16.1/tests/declare/best-of.eval.py +24 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/declare/compare-questions.eval.py +10 -3
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/declare/questions-attempts.eval.py +22 -5
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/declare/questions-group.eval.py +8 -3
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/declare/questions-state.eval.py +25 -6
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/test_checks.py +26 -5
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/test_conformance_context.py +12 -1
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/test_runner_attempts.py +46 -5
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/test_runner_checks.py +2 -1
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/test_runner_json.py +2 -2
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/test_runner_sdk.py +19 -3
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/test_types.py +1 -1
- {reeval_python-0.15.1 → reeval_python-0.16.1}/uv.lock +1 -1
- reeval_python-0.15.1/src/reeval_python/binaries.json +0 -55
- reeval_python-0.15.1/tests/context/judge.eval.py +0 -10
- {reeval_python-0.15.1 → reeval_python-0.16.1}/.gitignore +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/CHANGELOG.md +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/LICENSE +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/package.json +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/src/reeval_python/__main__.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/src/reeval_python/cli.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/src/reeval_python/declare.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/src/reeval_python/environment.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/src/reeval_python/errors.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/src/reeval_python/py.typed +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/src/reeval_python/runner.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/src/reeval_python/types.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/src/reeval_python/wire.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/context/abort.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/context/abort.sync.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/context/exec-retries.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/context/exec-retries.sync.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/context/exec.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/context/exec.sync.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/context/files.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/context/files.sync.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/context/record.async.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/context/record.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/context/send.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/context/send.sync.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/context/sync-async.async.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/context/sync-async.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/declare/compare-variants.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/declare/each-families.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/declare/egress-cascade.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/declare/environment-extend.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/declare/environment-plugin-marketplace.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/declare/environment-plugins.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/declare/groups-skip-todo.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/declare/revision.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/declare/tags.eval.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/runner_process.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/stdio_host.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/test_api.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/test_cli.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/test_conformance_declare.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/test_load.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/test_patterns.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/test_python_wheels.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/test_runner_isolation.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/test_runner_misuse.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/test_runner_stdio.py +0 -0
- {reeval_python-0.15.1 → reeval_python-0.16.1}/tests/test_source.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: reeval-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.16.1
|
|
4
4
|
Summary: Python authoring SDK for reeval (*.eval.py eval files)
|
|
5
5
|
Project-URL: Homepage, https://reeval.ai
|
|
6
6
|
Project-URL: Repository, https://github.com/invertase/reeval
|
|
@@ -73,7 +73,7 @@ from reeval_python import SyncAttemptContext, evaluate, expect
|
|
|
73
73
|
def lands(c: SyncAttemptContext) -> None:
|
|
74
74
|
c.send("Create greet.py that prints hi")
|
|
75
75
|
assert c.exec("test -f greet.py").ok
|
|
76
|
-
expect(c.judge("Does greet.py print hi?")).to_pass()
|
|
76
|
+
expect(c.judge("Does greet.py print hi?", contents=["greet.py"])).to_pass()
|
|
77
77
|
```
|
|
78
78
|
|
|
79
79
|
Plain `assert` is first-class, as in pytest: each one in an eval file is a check in the run
|
|
@@ -83,24 +83,33 @@ as in Python, and is recorded with its message and both sides of a comparison as
|
|
|
83
83
|
(`greet.py exists: assert 1 == 2`). An `AssertionError` the body catches isn't a failed check, so
|
|
84
84
|
a retry loop can assert; one the escaping error carries (each failure in a `TaskGroup`'s
|
|
85
85
|
`ExceptionGroup`, or one an error was raised from or while handling) is. Use typed results (`ExecResult.ok`, `Verdict.passed`, `Turn.text`, …) and `c.file(path)`
|
|
86
|
-
for quick checks. Keep `expect` for reeval matchers (`to_have_file`, `to_succeed`,
|
|
86
|
+
for quick checks. Keep `expect` for reeval matchers (`to_have_file`, `to_succeed`, checks that carry on,
|
|
87
87
|
labels) — Playwright-style.
|
|
88
88
|
|
|
89
|
-
####
|
|
89
|
+
#### Checks carry on; `expect.require` is a gate
|
|
90
90
|
|
|
91
|
-
A failed `expect` is
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
A failed `expect` is recorded and the body carries on, so every later check and judge still runs;
|
|
92
|
+
the attempt fails when the body ends. `expect.require` raises `ReevalAssertionError` instead, for a
|
|
93
|
+
gate the rest depends on:
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
c.send("Add a sign-up page")
|
|
97
|
+
expect.require(c.exec("npm run build"), "builds").to_succeed() # stops here if the build fails
|
|
98
|
+
expect(c.exec("npm test"), "tests pass").to_succeed() # recorded, carries on
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
reeval records a failed `expect.require` before the error reaches the body. One the body catches
|
|
102
|
+
still fails the attempt when the body ends, and its error says the eval caught it. A plain
|
|
103
|
+
`assert` the body catches records nothing, as in Python.
|
|
95
104
|
|
|
96
105
|
| The body catches | Recorded | Fails the attempt |
|
|
97
106
|
|---|---|---|
|
|
98
|
-
| a failed `expect(…)` | a failed check | yes, when the body ends |
|
|
107
|
+
| a failed `expect.require(…)` | a failed check | yes, when the body ends |
|
|
99
108
|
| a failed `assert` | nothing | no |
|
|
100
109
|
| neither (it escapes) | a failed check | yes |
|
|
101
110
|
|
|
102
111
|
So retry with `expect.poll`, which retries the matcher and records only its final outcome, or with
|
|
103
|
-
a plain `assert` or `if` in the loop, never `expect` in `try`/`except`:
|
|
112
|
+
a plain `assert` or `if` in the loop, never `expect.require` in `try`/`except`:
|
|
104
113
|
|
|
105
114
|
```python
|
|
106
115
|
# Retries the command until it succeeds, for up to 10 seconds: one check.
|
|
@@ -136,6 +145,13 @@ duration is seconds or a `timedelta`: `{"timeout": 90}`, `docker(start_timeout=t
|
|
|
136
145
|
`expect.poll(…, timeout=10)`. `docker()`, `fake_harness()`, `fake_judge()` and `plugin.*` return
|
|
137
146
|
values to pass as options, not data to edit.
|
|
138
147
|
|
|
148
|
+
`c.judge` takes the inputs the judge reads as keywords, and needs at least one: `diff=True`,
|
|
149
|
+
`contents=["src/**"]`, `output=True` with `on=result`, and so on. With none it raises `TypeError`.
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
expect(c.judge("Is it valid JSON?", on=result, output=True)).to_pass()
|
|
153
|
+
```
|
|
154
|
+
|
|
139
155
|
### `def` and `async def` bodies
|
|
140
156
|
|
|
141
157
|
A `def` body gets a blocking context: `c.exec(…)` runs the command and returns its `ExecResult`,
|
|
@@ -49,7 +49,7 @@ from reeval_python import SyncAttemptContext, evaluate, expect
|
|
|
49
49
|
def lands(c: SyncAttemptContext) -> None:
|
|
50
50
|
c.send("Create greet.py that prints hi")
|
|
51
51
|
assert c.exec("test -f greet.py").ok
|
|
52
|
-
expect(c.judge("Does greet.py print hi?")).to_pass()
|
|
52
|
+
expect(c.judge("Does greet.py print hi?", contents=["greet.py"])).to_pass()
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
Plain `assert` is first-class, as in pytest: each one in an eval file is a check in the run
|
|
@@ -59,24 +59,33 @@ as in Python, and is recorded with its message and both sides of a comparison as
|
|
|
59
59
|
(`greet.py exists: assert 1 == 2`). An `AssertionError` the body catches isn't a failed check, so
|
|
60
60
|
a retry loop can assert; one the escaping error carries (each failure in a `TaskGroup`'s
|
|
61
61
|
`ExceptionGroup`, or one an error was raised from or while handling) is. Use typed results (`ExecResult.ok`, `Verdict.passed`, `Turn.text`, …) and `c.file(path)`
|
|
62
|
-
for quick checks. Keep `expect` for reeval matchers (`to_have_file`, `to_succeed`,
|
|
62
|
+
for quick checks. Keep `expect` for reeval matchers (`to_have_file`, `to_succeed`, checks that carry on,
|
|
63
63
|
labels) — Playwright-style.
|
|
64
64
|
|
|
65
|
-
####
|
|
65
|
+
#### Checks carry on; `expect.require` is a gate
|
|
66
66
|
|
|
67
|
-
A failed `expect` is
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
A failed `expect` is recorded and the body carries on, so every later check and judge still runs;
|
|
68
|
+
the attempt fails when the body ends. `expect.require` raises `ReevalAssertionError` instead, for a
|
|
69
|
+
gate the rest depends on:
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
c.send("Add a sign-up page")
|
|
73
|
+
expect.require(c.exec("npm run build"), "builds").to_succeed() # stops here if the build fails
|
|
74
|
+
expect(c.exec("npm test"), "tests pass").to_succeed() # recorded, carries on
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
reeval records a failed `expect.require` before the error reaches the body. One the body catches
|
|
78
|
+
still fails the attempt when the body ends, and its error says the eval caught it. A plain
|
|
79
|
+
`assert` the body catches records nothing, as in Python.
|
|
71
80
|
|
|
72
81
|
| The body catches | Recorded | Fails the attempt |
|
|
73
82
|
|---|---|---|
|
|
74
|
-
| a failed `expect(…)` | a failed check | yes, when the body ends |
|
|
83
|
+
| a failed `expect.require(…)` | a failed check | yes, when the body ends |
|
|
75
84
|
| a failed `assert` | nothing | no |
|
|
76
85
|
| neither (it escapes) | a failed check | yes |
|
|
77
86
|
|
|
78
87
|
So retry with `expect.poll`, which retries the matcher and records only its final outcome, or with
|
|
79
|
-
a plain `assert` or `if` in the loop, never `expect` in `try`/`except`:
|
|
88
|
+
a plain `assert` or `if` in the loop, never `expect.require` in `try`/`except`:
|
|
80
89
|
|
|
81
90
|
```python
|
|
82
91
|
# Retries the command until it succeeds, for up to 10 seconds: one check.
|
|
@@ -112,6 +121,13 @@ duration is seconds or a `timedelta`: `{"timeout": 90}`, `docker(start_timeout=t
|
|
|
112
121
|
`expect.poll(…, timeout=10)`. `docker()`, `fake_harness()`, `fake_judge()` and `plugin.*` return
|
|
113
122
|
values to pass as options, not data to edit.
|
|
114
123
|
|
|
124
|
+
`c.judge` takes the inputs the judge reads as keywords, and needs at least one: `diff=True`,
|
|
125
|
+
`contents=["src/**"]`, `output=True` with `on=result`, and so on. With none it raises `TypeError`.
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
expect(c.judge("Is it valid JSON?", on=result, output=True)).to_pass()
|
|
129
|
+
```
|
|
130
|
+
|
|
115
131
|
### `def` and `async def` bodies
|
|
116
132
|
|
|
117
133
|
A `def` body gets a blocking context: `c.exec(…)` runs the command and returns its `ExecResult`,
|
|
@@ -17,14 +17,15 @@ from reeval_python.environment import (
|
|
|
17
17
|
plugin,
|
|
18
18
|
)
|
|
19
19
|
from reeval_python.errors import ReevalAssertionError, ReevalCallError
|
|
20
|
-
from reeval_python.expect import Expectation, expect
|
|
21
|
-
from reeval_python.options import EvalOptions, JudgeDefaults, JudgeOptions
|
|
20
|
+
from reeval_python.expect import Expectation, expect
|
|
21
|
+
from reeval_python.options import BestOf, EvalOptions, JudgeDefaults, JudgeOptions
|
|
22
22
|
from reeval_python.types import BackgroundHandle, Diff, ExecResult, FileChange, Turn, Verdict
|
|
23
23
|
|
|
24
24
|
__all__ = [
|
|
25
25
|
"DEFAULT_EGRESS_ALLOW",
|
|
26
26
|
"AttemptContext",
|
|
27
27
|
"BackgroundHandle",
|
|
28
|
+
"BestOf",
|
|
28
29
|
"Diff",
|
|
29
30
|
"DockerSandbox",
|
|
30
31
|
"Environment",
|
|
@@ -52,6 +53,5 @@ __all__ = [
|
|
|
52
53
|
"fake_judge",
|
|
53
54
|
"group",
|
|
54
55
|
"plugin",
|
|
55
|
-
"soft",
|
|
56
56
|
"todo",
|
|
57
57
|
]
|