[red-knot] Enforce specifying paths for mdtest code blocks in a separate preceding line (#15890)

## Summary

Resolves #15695, rework of #15704.

This change modifies the Mdtests framework so that:

* Paths must now be specified in a separate preceding line:

	`````markdown
	`a.py`:

	```py
	x = 1
	```
	`````

If the path of a file conflicts with its `lang`, an error will be
thrown.

* Configs are no longer accepted. The pattern still take them into
account, however, to avoid "Unterminated code block" errors.
* Unnamed files are now assigned unique, `lang`-respecting paths
automatically.

Additionally, all legacy usages have been updated.

## Test Plan

Unit tests and Markdown tests.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
This commit is contained in:
InSync 2025-02-04 14:27:17 +07:00 committed by GitHub
parent 0529ad67d7
commit 11cfe2ea8a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
35 changed files with 967 additions and 286 deletions

View file

@ -29,7 +29,9 @@ completing. The type of `x` at the beginning of the `except` suite in this examp
`x = could_raise_returns_str()` redefinition, but we *also* could have jumped to the `except` suite
*after* that redefinition.
```py path=union_type_inferred.py
`union_type_inferred.py`:
```py
def could_raise_returns_str() -> str:
return "foo"
@ -50,7 +52,9 @@ reveal_type(x) # revealed: str | Literal[2]
If `x` has the same type at the end of both branches, however, the branches unify and `x` is not
inferred as having a union type following the `try`/`except` block:
```py path=branches_unify_to_non_union_type.py
`branches_unify_to_non_union_type.py`:
```py
def could_raise_returns_str() -> str:
return "foo"
@ -133,7 +137,9 @@ the `except` suite:
- At the end of `else`, `x == 3`
- At the end of `except`, `x == 2`
```py path=single_except.py
`single_except.py`:
```py
def could_raise_returns_str() -> str:
return "foo"
@ -192,7 +198,9 @@ A `finally` suite is *always* executed. As such, if we reach the `reveal_type` c
this example, we know that `x` *must* have been reassigned to `2` during the `finally` suite. The
type of `x` at the end of the example is therefore `Literal[2]`:
```py path=redef_in_finally.py
`redef_in_finally.py`:
```py
def could_raise_returns_str() -> str:
return "foo"
@ -217,7 +225,9 @@ at this point than there were when we were inside the `finally` block.
(Our current model does *not* correctly infer the types *inside* `finally` suites, however; this is
still a TODO item for us.)
```py path=no_redef_in_finally.py
`no_redef_in_finally.py`:
```py
def could_raise_returns_str() -> str:
return "foo"
@ -249,7 +259,9 @@ suites:
exception raised in the `except` suite to cause us to jump to the `finally` suite before the
`except` suite ran to completion
```py path=redef_in_finally.py
`redef_in_finally.py`:
```py
def could_raise_returns_str() -> str:
return "foo"
@ -286,7 +298,9 @@ itself. (In some control-flow possibilities, some exceptions were merely *suspen
`finally` suite; these lead to the scope's termination following the conclusion of the `finally`
suite.)
```py path=no_redef_in_finally.py
`no_redef_in_finally.py`:
```py
def could_raise_returns_str() -> str:
return "foo"
@ -317,7 +331,9 @@ reveal_type(x) # revealed: str | bool
An example with multiple `except` branches and a `finally` branch:
```py path=multiple_except_branches.py
`multiple_except_branches.py`:
```py
def could_raise_returns_str() -> str:
return "foo"
@ -364,7 +380,9 @@ If the exception handler has an `else` branch, we must also take into account th
control flow could have jumped to the `finally` suite from partway through the `else` suite due to
an exception raised *there*.
```py path=single_except_branch.py
`single_except_branch.py`:
```py
def could_raise_returns_str() -> str:
return "foo"
@ -407,7 +425,9 @@ reveal_type(x) # revealed: bool | float
The same again, this time with multiple `except` branches:
```py path=multiple_except_branches.py
`multiple_except_branches.py`:
```py
def could_raise_returns_str() -> str:
return "foo"