Skip to content

Commit d8c9b42

Browse files
committed
refactor: allow walrus assignment inside lambdas
1 parent 0e14b4e commit d8c9b42

File tree

4 files changed

+460
-281
lines changed

4 files changed

+460
-281
lines changed

crates/djc-safe-eval/README.md

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@ It works by:
2020
Here we implement similar safety measures as Jinja.
2121
6. User receives back a function to evaluate the compiled code.
2222

23-
24-
5. **Runtime**: The generated code is evaluated with sandboxed interceptors that enforce security policies
25-
23+
7. **Runtime**: The generated code is evaluated with sandboxed interceptors that enforce security policies
2624

2725
This package is split in 2 parts:
2826

@@ -93,6 +91,33 @@ print(result) # 8
9391
print(context) # {"x": 4, "y": 8}
9492
```
9593

94+
Walrus operator can be used also inside comprehensions or lambdas:
95+
96+
```py
97+
# Comprehension
98+
compiled = safe_eval("[(x := y) for y in [1, 2, 3]]")
99+
context = {}
100+
result = compiled(context)
101+
print(context) # {"x": 3}
102+
103+
# Lambda
104+
compiled = safe_eval("fn_with_callback(on_done=lambda res: (data := res))")
105+
context = {"fn_with_callback": fn_with_callback}
106+
result = compiled(context)
107+
print(context) # {"data": {...}, "fn_with_callback": fn_with_callback}, }
108+
```
109+
110+
> **NOTE: This differs from regular Python, where walrus operator inside a function
111+
> will NOT leak out.**
112+
113+
If you try to assign a variable to the same value as an existing comprehension or
114+
lambda arguments, you will get a SyntaxError:
115+
116+
```py
117+
safe_eval("[(y := y) for y in [1, 2, 3]]") # SyntaxError
118+
safe_eval("lambda x: (x := 123))") # SyntaxError
119+
```
120+
96121
### Unsafe operations
97122

98123
Unsafe operations raise `SecurityError`. See all unsafe scenarios in [What is unsafe?](#what-is-unsafe)
@@ -259,13 +284,11 @@ Almost anything that is a valid Python expression is allowed:
259284

260285
### Variable scoping
261286

262-
The transformer correctly handles Python's scoping rules:
287+
The transformer matches Python's scoping rules for comprehensions and lambdas, but diverges for walrus assignments:
263288

264289
- **Comprehensions**: Variables introduced in comprehensions are local to the comprehension (e.g., `x` in `[x for x in items]`)
265290
- **Lambda parameters**: Lambda parameters are local to the lambda and not transformed
266-
- **Walrus operator**:
267-
- In comprehensions: Walrus assignments remain available OUTSIDE of comprehensions
268-
- In lambdas: Walrus assignments are NOT available outside
291+
- **Walrus operator**: Walrus assignments remain available outside of comprehensions or lambdas.(diverges from Python)
269292

270293
## Performance
271294

@@ -348,6 +371,7 @@ The version of `ruff` is locked to a specific commit or tag, documented in `.git
348371
```
349372

350373
4. Navigate back and commit the change:
374+
351375
```bash
352376
cd ../../..
353377
git add .gitmodules crates/djc-safe-eval/submodules/ruff

0 commit comments

Comments
 (0)