Skip to content

Commit 6cf8481

Browse files
committed
Merge branch 'main' into dcreager/two-phase-binding
* main: [playground] Avoid concurrent deployments (#16834) [red-knot] Infer `lambda` return type as `Unknown` (#16695) [red-knot] Move `name` field on parameter kind (#16830) [red-knot] Emit errors for more AST nodes that are invalid (or only valid in specific contexts) in type expressions (#16822) [playground] Use cursor for clickable elements (#16833) [red-knot] Deploy playground on main (#16832) Red Knot Playground (#12681) [syntax-errors] PEP 701 f-strings before Python 3.12 (#16543)
2 parents 6a3bc70 + 81759be commit 6cf8481

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+4902
-638
lines changed

.github/workflows/ci.yaml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -736,10 +736,9 @@ jobs:
736736
- name: "Install Node dependencies"
737737
run: npm ci
738738
working-directory: playground
739-
- name: "Build Ruff playground"
740-
run: npm run dev:build --workspace ruff-playground
739+
- name: "Build playgrounds"
740+
run: npm run dev:wasm
741741
working-directory: playground
742-
# Requires a build for ruff_wasm to exist
743742
- name: "Run TypeScript checks"
744743
run: npm run check
745744
working-directory: playground
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Publish the Red Knot playground.
2+
name: "[Knot Playground] Release"
3+
4+
permissions: {}
5+
6+
on:
7+
push:
8+
branches: [main]
9+
paths:
10+
- "crates/red_knot*/**"
11+
- "crates/ruff_db"
12+
- "crates/ruff_python_ast"
13+
- "crates/ruff_python_parser"
14+
- "playground"
15+
- ".github/workflows/publish-knot-playground.yml"
16+
17+
concurrency:
18+
group: ${{ github.workflow }}-${{ github.ref_name }}
19+
cancel-in-progress: true
20+
21+
env:
22+
CARGO_INCREMENTAL: 0
23+
CARGO_NET_RETRY: 10
24+
CARGO_TERM_COLOR: always
25+
RUSTUP_MAX_RETRIES: 10
26+
27+
jobs:
28+
publish:
29+
runs-on: ubuntu-latest
30+
env:
31+
CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }}
32+
steps:
33+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
34+
with:
35+
persist-credentials: false
36+
- name: "Install Rust toolchain"
37+
run: rustup target add wasm32-unknown-unknown
38+
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
39+
with:
40+
node-version: 22
41+
- uses: jetli/wasm-bindgen-action@20b33e20595891ab1a0ed73145d8a21fc96e7c29 # v0.2.0
42+
- name: "Install Node dependencies"
43+
run: npm ci
44+
working-directory: playground
45+
- name: "Run TypeScript checks"
46+
run: npm run check
47+
working-directory: playground
48+
- name: "Build Knot playground"
49+
run: npm run build --workspace knot-playground
50+
working-directory: playground
51+
- name: "Deploy to Cloudflare Pages"
52+
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
53+
uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 # v3.14.1
54+
with:
55+
apiToken: ${{ secrets.CF_API_TOKEN }}
56+
accountId: ${{ secrets.CF_ACCOUNT_ID }}
57+
# `github.head_ref` is only set during pull requests and for manual runs or tags we use `main` to deploy to production
58+
command: pages deploy playground/knot/dist --project-name=knot-playground --branch ${{ github.head_ref || 'main' }} --commit-hash ${GITHUB_SHA}

.github/workflows/publish-playground.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@ jobs:
3838
- name: "Install Node dependencies"
3939
run: npm ci
4040
working-directory: playground
41-
- name: "Build Ruff playground"
42-
run: npm run build --workspace ruff-playground
43-
working-directory: playground
4441
- name: "Run TypeScript checks"
4542
run: npm run check
4643
working-directory: playground
44+
- name: "Build Ruff playground"
45+
run: npm run build --workspace ruff-playground
46+
working-directory: playground
4747
- name: "Deploy to Cloudflare Pages"
4848
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
4949
uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 # v3.14.1

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/red_knot_python_semantic/resources/mdtest/annotations/invalid.md

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,60 @@ def _(
4747
## Invalid AST nodes
4848

4949
```py
50+
def bar() -> None:
51+
return None
52+
5053
def _(
5154
a: 1, # error: [invalid-type-form] "Int literals are not allowed in this context in a type expression"
5255
b: 2.3, # error: [invalid-type-form] "Float literals are not allowed in type expressions"
5356
c: 4j, # error: [invalid-type-form] "Complex literals are not allowed in type expressions"
5457
d: True, # error: [invalid-type-form] "Boolean literals are not allowed in this context in a type expression"
55-
# error: [invalid-type-form] "Bytes literals are not allowed in this context in a type expression"
56-
e: int | b"foo",
58+
e: int | b"foo", # error: [invalid-type-form] "Bytes literals are not allowed in this context in a type expression"
59+
f: 1 and 2, # error: [invalid-type-form] "Boolean operations are not allowed in type expressions"
60+
g: 1 or 2, # error: [invalid-type-form] "Boolean operations are not allowed in type expressions"
61+
h: (foo := 1), # error: [invalid-type-form] "Named expressions are not allowed in type expressions"
62+
i: not 1, # error: [invalid-type-form] "Unary operations are not allowed in type expressions"
63+
j: lambda: 1, # error: [invalid-type-form] "`lambda` expressions are not allowed in type expressions"
64+
k: 1 if True else 2, # error: [invalid-type-form] "`if` expressions are not allowed in type expressions"
65+
l: await 1, # error: [invalid-type-form] "`await` expressions are not allowed in type expressions"
66+
m: (yield 1), # error: [invalid-type-form] "`yield` expressions are not allowed in type expressions"
67+
n: (yield from [1]), # error: [invalid-type-form] "`yield from` expressions are not allowed in type expressions"
68+
o: 1 < 2, # error: [invalid-type-form] "Comparison expressions are not allowed in type expressions"
69+
p: bar(), # error: [invalid-type-form] "Function calls are not allowed in type expressions"
70+
q: int | f"foo", # error: [invalid-type-form] "F-strings are not allowed in type expressions"
71+
r: [1, 2, 3][1:2], # error: [invalid-type-form] "Slices are not allowed in type expressions"
5772
):
5873
reveal_type(a) # revealed: Unknown
5974
reveal_type(b) # revealed: Unknown
6075
reveal_type(c) # revealed: Unknown
6176
reveal_type(d) # revealed: Unknown
6277
reveal_type(e) # revealed: int | Unknown
78+
reveal_type(f) # revealed: Unknown
79+
reveal_type(g) # revealed: Unknown
80+
reveal_type(h) # revealed: Unknown
81+
reveal_type(i) # revealed: Unknown
82+
reveal_type(j) # revealed: Unknown
83+
reveal_type(k) # revealed: Unknown
84+
reveal_type(p) # revealed: Unknown
85+
reveal_type(q) # revealed: int | Unknown
86+
reveal_type(r) # revealed: @Todo(generics)
87+
```
88+
89+
## Invalid Collection based AST nodes
90+
91+
```py
92+
def _(
93+
a: {1: 2}, # error: [invalid-type-form] "Dict literals are not allowed in type expressions"
94+
b: {1, 2}, # error: [invalid-type-form] "Set literals are not allowed in type expressions"
95+
c: {k: v for k, v in [(1, 2)]}, # error: [invalid-type-form] "Dict comprehensions are not allowed in type expressions"
96+
d: [k for k in [1, 2]], # error: [invalid-type-form] "List comprehensions are not allowed in type expressions"
97+
e: {k for k in [1, 2]}, # error: [invalid-type-form] "Set comprehensions are not allowed in type expressions"
98+
f: (k for k in [1, 2]), # error: [invalid-type-form] "Generator expressions are not allowed in type expressions"
99+
):
100+
reveal_type(a) # revealed: Unknown
101+
reveal_type(b) # revealed: Unknown
102+
reveal_type(c) # revealed: Unknown
103+
reveal_type(d) # revealed: Unknown
104+
reveal_type(e) # revealed: Unknown
105+
reveal_type(f) # revealed: Unknown
63106
```

crates/red_knot_python_semantic/resources/mdtest/expression/lambda.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
`lambda` expressions can be defined without any parameters.
66

77
```py
8-
reveal_type(lambda: 1) # revealed: () -> @Todo(lambda return type)
8+
reveal_type(lambda: 1) # revealed: () -> Unknown
99

1010
# error: [unresolved-reference]
11-
reveal_type(lambda: a) # revealed: () -> @Todo(lambda return type)
11+
reveal_type(lambda: a) # revealed: () -> Unknown
1212
```
1313

1414
## With parameters
@@ -17,45 +17,45 @@ Unlike parameters in function definition, the parameters in a `lambda` expressio
1717
annotated.
1818

1919
```py
20-
reveal_type(lambda a: a) # revealed: (a) -> @Todo(lambda return type)
21-
reveal_type(lambda a, b: a + b) # revealed: (a, b) -> @Todo(lambda return type)
20+
reveal_type(lambda a: a) # revealed: (a) -> Unknown
21+
reveal_type(lambda a, b: a + b) # revealed: (a, b) -> Unknown
2222
```
2323

2424
But, it can have default values:
2525

2626
```py
27-
reveal_type(lambda a=1: a) # revealed: (a=Literal[1]) -> @Todo(lambda return type)
28-
reveal_type(lambda a, b=2: a) # revealed: (a, b=Literal[2]) -> @Todo(lambda return type)
27+
reveal_type(lambda a=1: a) # revealed: (a=Literal[1]) -> Unknown
28+
reveal_type(lambda a, b=2: a) # revealed: (a, b=Literal[2]) -> Unknown
2929
```
3030

3131
And, positional-only parameters:
3232

3333
```py
34-
reveal_type(lambda a, b, /, c: c) # revealed: (a, b, /, c) -> @Todo(lambda return type)
34+
reveal_type(lambda a, b, /, c: c) # revealed: (a, b, /, c) -> Unknown
3535
```
3636

3737
And, keyword-only parameters:
3838

3939
```py
40-
reveal_type(lambda a, *, b=2, c: b) # revealed: (a, *, b=Literal[2], c) -> @Todo(lambda return type)
40+
reveal_type(lambda a, *, b=2, c: b) # revealed: (a, *, b=Literal[2], c) -> Unknown
4141
```
4242

4343
And, variadic parameter:
4444

4545
```py
46-
reveal_type(lambda *args: args) # revealed: (*args) -> @Todo(lambda return type)
46+
reveal_type(lambda *args: args) # revealed: (*args) -> Unknown
4747
```
4848

4949
And, keyword-varidic parameter:
5050

5151
```py
52-
reveal_type(lambda **kwargs: kwargs) # revealed: (**kwargs) -> @Todo(lambda return type)
52+
reveal_type(lambda **kwargs: kwargs) # revealed: (**kwargs) -> Unknown
5353
```
5454

5555
Mixing all of them together:
5656

5757
```py
58-
# revealed: (a, b, /, c=Literal[True], *args, *, d=Literal["default"], e=Literal[5], **kwargs) -> @Todo(lambda return type)
58+
# revealed: (a, b, /, c=Literal[True], *args, *, d=Literal["default"], e=Literal[5], **kwargs) -> Unknown
5959
reveal_type(lambda a, b, /, c=True, *args, d="default", e=5, **kwargs: None)
6060
```
6161

@@ -96,5 +96,5 @@ Here, a `lambda` expression is used as the default value for a parameter in anot
9696
expression.
9797

9898
```py
99-
reveal_type(lambda a=lambda x, y: 0: 2) # revealed: (a=(x, y) -> @Todo(lambda return type)) -> @Todo(lambda return type)
99+
reveal_type(lambda a=lambda x, y: 0: 2) # revealed: (a=(x, y) -> Unknown) -> Unknown
100100
```

0 commit comments

Comments
 (0)