Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
eb75b05
Update update_data.py: make the space in error comments optional
wyattscarpenter Jul 30, 2025
8bb4ff6
Update README.md: docu for the spacedness thing
wyattscarpenter Jul 30, 2025
47f82d4
Update data.py: continue implementing optional spacedness
wyattscarpenter Jul 30, 2025
25b28c9
Update data.py: actually use re split
wyattscarpenter Jul 30, 2025
9705f73
Update data.py: use raw strings
wyattscarpenter Jul 30, 2025
59a14cb
Update README.md: remember that markdown also uses backslash escapes
wyattscarpenter Jul 30, 2025
ba6afdb
be more strict, but also more lenient, about error code comment format
wyattscarpenter Jul 31, 2025
467fdf1
message may include leading spaces
wyattscarpenter Jul 31, 2025
a56bebc
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 31, 2025
a429c05
Handle zero-indent case in rewrite
wyattscarpenter Jul 31, 2025
796adda
fix broken tests, elaborate on test file format in the readme
wyattscarpenter Jul 31, 2025
33504bb
I hate black param wrapping on things that should be a single line
wyattscarpenter Jul 31, 2025
1bc3676
make tests
wyattscarpenter Jul 31, 2025
fd636a1
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 31, 2025
55f3e68
typo
wyattscarpenter Jul 31, 2025
bcaef32
Merge branch 'master' into espace
wyattscarpenter Jan 10, 2026
4d72ec8
Apply suggestion from @wyattscarpenter
wyattscarpenter Feb 14, 2026
376c81e
Let any unescaped # character terminate a comment
wyattscarpenter Feb 24, 2026
df800b8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 24, 2026
2f7b99b
let the column number also have arbitrary spacing
wyattscarpenter Feb 24, 2026
0ba4577
fix spaces paren grouping
wyattscarpenter Feb 24, 2026
8791ea0
accomodate urls again
wyattscarpenter Feb 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions mypy/test/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -545,9 +545,10 @@ def expand_errors(input: list[str], output: list[str], fnam: str) -> None:

for i in range(len(input)):
# The first in the split things isn't a comment
for possible_err_comment in input[i].split(" # ")[1:]:
for possible_err_comment in re.split(r"(?!\\)#\s*(?=[ENW]\s*:)", input[i])[1:]:
m = re.search(
r"^([ENW]):((?P<col>\d+):)? (?P<message>.*)$", possible_err_comment.strip()
r"^([ENW])\s*:(\s*(?P<col>\d+)\s*:)?(?P<message>(?:\\#|[^#]|\S#)*)$",
possible_err_comment.strip(),
)
if m:
if m.group(1) == "E":
Expand All @@ -558,11 +559,12 @@ def expand_errors(input: list[str], output: list[str], fnam: str) -> None:
severity = "warning"
col = m.group("col")
message = m.group("message")
message = message.replace("\\#", "#") # adds back escaped # character
message = message.replace(r"\#", "#") # adds back escaped # character
# Message may, and probably does, include leading spaces
if col is None:
output.append(f"{fnam}:{i + 1}: {severity}: {message}")
output.append(f"{fnam}:{i + 1}: {severity}:{message}")
else:
output.append(f"{fnam}:{i + 1}:{col}: {severity}: {message}")
output.append(f"{fnam}:{i + 1}:{col}: {severity}:{message}")


def fix_win_path(line: str) -> str:
Expand Down
2 changes: 1 addition & 1 deletion mypy/test/update_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def _iter_fixes(
fix_lines = []
for lineno, source_line in enumerate(source_lines, start=1):
reports = reports_by_line.get((file_path, lineno))
comment_match = re.search(r"(?P<indent>\s+)(?P<comment># [EWN]: .+)$", source_line)
comment_match = re.search(r"(?P<indent>\s*)(?P<comment>#\s*[EWN]\s*:.+)$", source_line)
if comment_match:
source_line = source_line[: comment_match.start("indent")] # strip old comment
if reports:
Expand Down
18 changes: 12 additions & 6 deletions test-data/unit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,23 @@ with text "abc..."
- note a space after `E:` and `flags:`
- `# E:12` adds column number to the expected error
- use `\` to escape the `#` character and indicate that the rest of the line is part of
the error message
the error message (note that there is no support for using `\\` to escape a backslash itself
in this context; also, in all other contexts, such as line-continuation, the backslash is treated
as it normally would be in a python source file)
- repeating `# E: ` several times in one line indicates multiple expected errors in one line
- `W: ...` and `N: ...` works exactly like `E: ...`, but report a warning and a note respectively
- `W: ...` and `N: ...` work exactly like `E: ...`, but report a warning and a note respectively
- lines that don't contain the above should cause no type check errors
- lines that begin with `--` are test-file-format comments, and will not appear in the tested python
source code
- some test files are run in a special way by the test runner; this is typically documented in
test-file-format comments at the top of the test file
- optional `[builtins fixtures/...]` tells the type checker to use
`builtins` stubs from the indicated file (see Fixtures section below)
- optional `[out]` is an alternative to the `# E: ` notation: it indicates that
any text after it contains the expected type checking error messages.
Usually, `# E: ` is preferred because it makes it easier to associate the
errors with the code generating them at a glance, and to change the code of
the test without having to change line numbers in `[out]`
any text after it contains the expected type checking error messages.
Usually, `# E: ` is preferred because it makes it easier to associate the
errors with the code generating them at a glance, and to change the code of
the test without having to change line numbers in `[out]`
- an empty `[out]` section has no effect
- to add tests for a feature that hasn't been implemented yet, append `-xfail`
to the end of the test name
Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/check-classes.test
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,7 @@ class A:
def __replace__(self, x: Optional[str]) -> Self: pass

class B(A):
def __replace__(self, x: str) -> Self: pass # E: \
def __replace__(self, x: str) -> Self: pass \
# E: Argument 1 of "__replace__" is incompatible with supertype "A"; supertype defines the argument type as "str | None" [override] \
# N: This violates the Liskov substitution principle \
# N: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides
Expand Down
3 changes: 2 additions & 1 deletion test-data/unit/check-deprecated.test
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ from typing_extensions import deprecated
@deprecated("use f2 instead")
def f() -> None: ...

f # E: function __main__.f is deprecated: use f2 instead # type: ignore[deprecated]
f # type: ignore[deprecated]
f # E: function __main__.f is deprecated: use f2 instead
f(1) # E: function __main__.f is deprecated: use f2 instead \
# E: Too many arguments for "f"
f[1] # E: function __main__.f is deprecated: use f2 instead \
Expand Down
49 changes: 49 additions & 0 deletions test-data/unit/check-error-comments.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
[case noErrorComment]
x: int = 1

[case prototypicalErrorComment]
x: int = "hi" # E: Incompatible types in assignment (expression has type "str", variable has type "int")

[case emptyLineErrorComment-xfail]
# E:

[case oddErrorComments]
x: int = "hi"#E: Incompatible types in assignment (expression has type "str", variable has type "int")
x2: int = "hi" #E: Incompatible types in assignment (expression has type "str", variable has type "int")
x3: int = "hi" # E: Incompatible types in assignment (expression has type "str", variable has type "int")
x4: int = "hi" # E : Incompatible types in assignment (expression has type "str", variable has type "int")
x5: int = "hi" # E : Incompatible types in assignment (expression has type "str", variable has type "int")
x6: int = "hi" # E : Incompatible types in assignment (expression has type "str", variable has type "int")
x7: int = "hi" # E : Incompatible types in assignment (expression has type "str", variable has type "int")
x8: int = "hi" \
# E : Incompatible types in assignment (expression has type "str", variable has type "int")
x82: int = "hi"\
# E : Incompatible types in assignment (expression has type "str", variable has type "int")

[case oddErrorCommentsNoteComment]
n: int
reveal_type(n) # N: Revealed type is "builtins.int"


[case oddErrorCommentsThatDontWork-xfail]
-- The space between the ":" and the message actually differs in the output, which we match against
-- so we can't just parse it and replace it; therefore, these do not work.
x: int = "hi"#E:Incompatible types in assignment (expression has type "str", variable has type "int")
x2: int = "hi" #E:Incompatible types in assignment (expression has type "str", variable has type "int")
x3: int = "hi" # E : Incompatible types in assignment (expression has type "str", variable has type "int")
x4: int = "hi" # E : Incompatible types in assignment (expression has type "str", variable has type "int")
x5: int = "hi" # E : Incompatible types in assignment (expression has type "str", variable has type "int")

[case oddErrorCommentsThatDontWorkCase-xfail]
-- I just didn't bother to implement these.
x: int = "hi" # e: Incompatible types in assignment (expression has type "str", variable has type "int")
x: int = "hi" # w: Incompatible types in assignment (expression has type "str", variable has type "int")
x: int = "hi" # n: Incompatible types in assignment (expression has type "str", variable has type "int")


[case oddErrorCommentsThatDontWorkCaseAndNoColon-xfail]
-- I didn't implement these. This is veering towards the ambiguous.
x: int = "hi" # e: Incompatible types in assignment (expression has type "str", variable has type "int")
x2: int = "hi" # E Incompatible types in assignment (expression has type "str", variable has type "int")
x3: int = "hi" # e Incompatible types in assignment (expression has type "str", variable has type "int")
x4: int = "hi" # e Incompatible types in assignment (expression has type "str", variable has type "int")
2 changes: 1 addition & 1 deletion test-data/unit/check-newsemanal.test
Original file line number Diff line number Diff line change
Expand Up @@ -2673,7 +2673,7 @@ class C:
) -> str:
return 0 # E: Incompatible return value type (got "int", expected "str")

reveal_type(C.X) # E: # N: Revealed type is "def () -> __main__.X"
reveal_type(C.X) # N: Revealed type is "def () -> __main__.X"
reveal_type(C().str()) # N: Revealed type is "builtins.str"

[case testNewAnalyzerNameNotDefinedYetInClassBody]
Expand Down
17 changes: 11 additions & 6 deletions test-data/unit/check-type-aliases.test
Original file line number Diff line number Diff line change
Expand Up @@ -551,12 +551,7 @@ def take_id(x: Id[int]) -> None:
def id(x: Id[T]) -> T:
return x

# TODO: This doesn't work and maybe it should?
# Indirection = AnInt[T]
# y: Indirection[str]
# reveal_type(y) # E : Revealed type is "builtins.int"

# But this does
# Contrast with the TODO below
Indirection2 = FlexibleAlias[T, AnInt[T]]
z: Indirection2[str]
reveal_type(z) # N: Revealed type is "builtins.int"
Expand All @@ -567,6 +562,16 @@ reveal_type(w) # N: Revealed type is "builtins.int"

[builtins fixtures/dict.pyi]

[case testFlexibleAlias1Todo-xfail]
# TODO: This doesn't work and maybe it should?
# Contrast with the example above that mentions this todo
T = TypeVar('T')
AnInt = FlexibleAlias[T, int]
Indirection = AnInt[T]
y: Indirection[str]
reveal_type(y) # N : Revealed type is "builtins.int"


[case testFlexibleAlias2]
# flags: --always-true=BOGUS
from typing import TypeVar, Any
Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/check-typeddict.test
Original file line number Diff line number Diff line change
Expand Up @@ -3926,7 +3926,7 @@ reveal_type(X) # N: Revealed type is "builtins.dict[builtins.str, def () -> bui
from typing_extensions import TypeAlias
X: TypeAlias = {"int": int, "str": str}
x: X
reveal_type(x) # N: # N: Revealed type is "TypedDict({'int': builtins.int, 'str': builtins.str})"
reveal_type(x) # N: Revealed type is "TypedDict({'int': builtins.int, 'str': builtins.str})"
[builtins fixtures/dict.pyi]
[typing fixtures/typing-typeddict.pyi]

Expand Down
Loading