From f3a538ace946c6872dad157e733e506ab20c3aa6 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Fri, 1 Oct 2021 14:11:29 +0300 Subject: [PATCH 1/5] Improves error message for parsing `slice` in annotations, refs #10266 --- mypy/fastparse.py | 6 ++++-- test-data/unit/parse.test | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 2f4122bf3bfa..7620bd54c644 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -130,6 +130,8 @@ def ast3_parse(source: Union[str, bytes], filename: str, mode: str, INVALID_TYPE_IGNORE: Final = 'Invalid "type: ignore" comment' +INVALID_SLICE_ERROR: Final = 'Slice usage in type annotation is invalid, consider using "slice()" or "{}"' + TYPE_IGNORE_PATTERN = re.compile(r'[^#]*#\s*type:\s*ignore\s*(.*)') @@ -1560,12 +1562,12 @@ def visit_Subscript(self, n: ast3.Subscript) -> Type: if (isinstance(sliceval, ast3.Slice) or (isinstance(sliceval, ast3.Tuple) and any(isinstance(x, ast3.Slice) for x in sliceval.elts))): - self.fail(TYPE_COMMENT_SYNTAX_ERROR, self.line, getattr(n, 'col_offset', -1)) + self.fail(INVALID_SLICE_ERROR, self.line, getattr(n, 'col_offset', -1)) return AnyType(TypeOfAny.from_error) else: # Python 3.8 or earlier use a different AST structure for subscripts if not isinstance(n.slice, Index): - self.fail(TYPE_COMMENT_SYNTAX_ERROR, self.line, getattr(n, 'col_offset', -1)) + self.fail(INVALID_SLICE_ERROR, self.line, getattr(n, 'col_offset', -1)) return AnyType(TypeOfAny.from_error) sliceval = n.slice.value diff --git a/test-data/unit/parse.test b/test-data/unit/parse.test index 22b1ab28481d..e66441d3537d 100644 --- a/test-data/unit/parse.test +++ b/test-data/unit/parse.test @@ -949,6 +949,42 @@ main:1: error: invalid syntax [out version>=3.10] main:1: error: invalid syntax. Perhaps you forgot a comma? +[case testSliceInAnnotation39] +# flags: --python-version 3.9 +a: Annotated[int, 1:2] # E: Slice usage in type annotation is invalid, consider using "slice()" or "{}" +b: Dict[int, x:y] # E: Slice usage in type annotation is invalid, consider using "slice()" or "{}" +c: Dict[x:y] # E: Slice usage in type annotation is invalid, consider using "slice()" or "{}" +[out] + +[case testSliceInAnnotation38] +# flags: --python-version 3.8 +a: Annotated[int, 1:2] # E: Slice usage in type annotation is invalid, consider using "slice()" or "{}" +b: Dict[int, x:y] # E: Slice usage in type annotation is invalid, consider using "slice()" or "{}" +c: Dict[x:y] # E: Slice usage in type annotation is invalid, consider using "slice()" or "{}" +[out] + +[case testSliceInAnnotationTypeComment39] +# flags: --python-version 3.9 +a = None # type: Annotated[int, 1:2] # E: Slice usage in type annotation is invalid, consider using "slice()" or "{}" +b = None # type: Dict[int, x:y] # E: Slice usage in type annotation is invalid, consider using "slice()" or "{}" +c = None # type: Dict[x:y] # E: Slice usage in type annotation is invalid, consider using "slice()" or "{}" +[out] + +[case testSliceInList39] +# flags: --python-version 3.9 +x = [1, 2][1:2] +[out] +MypyFile:1( + AssignmentStmt:2( + NameExpr(x) + IndexExpr:2( + ListExpr:2( + IntExpr(1) + IntExpr(2)) + SliceExpr:2( + IntExpr(1) + IntExpr(2))))) + [case testDictionaryExpression] {} {1:x} From 069fcf0097a9ef9f09dfbf13cf145d16a381f93f Mon Sep 17 00:00:00 2001 From: sobolevn Date: Fri, 1 Oct 2021 14:13:48 +0300 Subject: [PATCH 2/5] Fixes flake8 --- mypy/fastparse.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 7620bd54c644..3376bbb68cb0 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -130,7 +130,9 @@ def ast3_parse(source: Union[str, bytes], filename: str, mode: str, INVALID_TYPE_IGNORE: Final = 'Invalid "type: ignore" comment' -INVALID_SLICE_ERROR: Final = 'Slice usage in type annotation is invalid, consider using "slice()" or "{}"' +INVALID_SLICE_ERROR: Final = ( + 'Slice usage in type annotation is invalid, consider using "slice()" or "{}"' +) TYPE_IGNORE_PATTERN = re.compile(r'[^#]*#\s*type:\s*ignore\s*(.*)') From e8a9be19a821674f53cd6d6711ed66f16653294d Mon Sep 17 00:00:00 2001 From: sobolevn Date: Fri, 1 Oct 2021 14:23:40 +0300 Subject: [PATCH 3/5] Adds more tests --- test-data/unit/parse.test | 46 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/test-data/unit/parse.test b/test-data/unit/parse.test index e66441d3537d..72ccaace5e88 100644 --- a/test-data/unit/parse.test +++ b/test-data/unit/parse.test @@ -970,6 +970,52 @@ b = None # type: Dict[int, x:y] # E: Slice usage in type annotation is invalid c = None # type: Dict[x:y] # E: Slice usage in type annotation is invalid, consider using "slice()" or "{}" [out] +[case testCorrectSlicesInAnnotations39] +# flags: --python-version 3.9 +a: Annotated[int, slice(1, 2)] +b: Dict[int, {x:y}] +c: Dict[{x:y}] +[out] +MypyFile:1( + AssignmentStmt:2( + NameExpr(a) + TempNode:2( + Any) + Annotated?[int?, None]) + AssignmentStmt:3( + NameExpr(b) + TempNode:3( + Any) + Dict?[int?, None]) + AssignmentStmt:4( + NameExpr(c) + TempNode:4( + Any) + Dict?[None])) + +[case testCorrectSlicesInAnnotations38] +# flags: --python-version 3.8 +a: Annotated[int, slice(1, 2)] +b: Dict[int, {x:y}] +c: Dict[{x:y}] +[out] +MypyFile:1( + AssignmentStmt:2( + NameExpr(a) + TempNode:2( + Any) + Annotated?[int?, None]) + AssignmentStmt:3( + NameExpr(b) + TempNode:3( + Any) + Dict?[int?, None]) + AssignmentStmt:4( + NameExpr(c) + TempNode:4( + Any) + Dict?[None])) + [case testSliceInList39] # flags: --python-version 3.9 x = [1, 2][1:2] From 61eb993917691dd086d84739a185c3ef7fd17ff1 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Fri, 1 Oct 2021 15:01:33 +0300 Subject: [PATCH 4/5] Fixes test --- test-data/unit/check-fastparse.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-data/unit/check-fastparse.test b/test-data/unit/check-fastparse.test index 497ed9b1d2b2..ff61179eaff9 100644 --- a/test-data/unit/check-fastparse.test +++ b/test-data/unit/check-fastparse.test @@ -322,7 +322,7 @@ x @= 1 from typing import Dict x = None # type: Dict[x: y] [out] -main:3: error: syntax error in type comment +main:3: error: Slice usage in type annotation is invalid, consider using "slice()" or "{}" [case testPrintStatementTrailingCommaFastParser_python2] From 5f2bff28bba4152e91c834da664de501bd30662d Mon Sep 17 00:00:00 2001 From: sobolevn Date: Fri, 1 Oct 2021 20:13:00 +0300 Subject: [PATCH 5/5] Addresses review --- mypy/fastparse.py | 4 +--- test-data/unit/check-fastparse.test | 2 +- test-data/unit/parse.test | 18 +++++++++--------- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 3376bbb68cb0..386bfb94800c 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -130,9 +130,7 @@ def ast3_parse(source: Union[str, bytes], filename: str, mode: str, INVALID_TYPE_IGNORE: Final = 'Invalid "type: ignore" comment' -INVALID_SLICE_ERROR: Final = ( - 'Slice usage in type annotation is invalid, consider using "slice()" or "{}"' -) +INVALID_SLICE_ERROR: Final = 'Slice usage in type annotation is invalid' TYPE_IGNORE_PATTERN = re.compile(r'[^#]*#\s*type:\s*ignore\s*(.*)') diff --git a/test-data/unit/check-fastparse.test b/test-data/unit/check-fastparse.test index ff61179eaff9..03aa1e4c3214 100644 --- a/test-data/unit/check-fastparse.test +++ b/test-data/unit/check-fastparse.test @@ -322,7 +322,7 @@ x @= 1 from typing import Dict x = None # type: Dict[x: y] [out] -main:3: error: Slice usage in type annotation is invalid, consider using "slice()" or "{}" +main:3: error: Slice usage in type annotation is invalid [case testPrintStatementTrailingCommaFastParser_python2] diff --git a/test-data/unit/parse.test b/test-data/unit/parse.test index 72ccaace5e88..f9bbb7dda5a4 100644 --- a/test-data/unit/parse.test +++ b/test-data/unit/parse.test @@ -951,23 +951,23 @@ main:1: error: invalid syntax. Perhaps you forgot a comma? [case testSliceInAnnotation39] # flags: --python-version 3.9 -a: Annotated[int, 1:2] # E: Slice usage in type annotation is invalid, consider using "slice()" or "{}" -b: Dict[int, x:y] # E: Slice usage in type annotation is invalid, consider using "slice()" or "{}" -c: Dict[x:y] # E: Slice usage in type annotation is invalid, consider using "slice()" or "{}" +a: Annotated[int, 1:2] # E: Slice usage in type annotation is invalid +b: Dict[int, x:y] # E: Slice usage in type annotation is invalid +c: Dict[x:y] # E: Slice usage in type annotation is invalid [out] [case testSliceInAnnotation38] # flags: --python-version 3.8 -a: Annotated[int, 1:2] # E: Slice usage in type annotation is invalid, consider using "slice()" or "{}" -b: Dict[int, x:y] # E: Slice usage in type annotation is invalid, consider using "slice()" or "{}" -c: Dict[x:y] # E: Slice usage in type annotation is invalid, consider using "slice()" or "{}" +a: Annotated[int, 1:2] # E: Slice usage in type annotation is invalid +b: Dict[int, x:y] # E: Slice usage in type annotation is invalid +c: Dict[x:y] # E: Slice usage in type annotation is invalid [out] [case testSliceInAnnotationTypeComment39] # flags: --python-version 3.9 -a = None # type: Annotated[int, 1:2] # E: Slice usage in type annotation is invalid, consider using "slice()" or "{}" -b = None # type: Dict[int, x:y] # E: Slice usage in type annotation is invalid, consider using "slice()" or "{}" -c = None # type: Dict[x:y] # E: Slice usage in type annotation is invalid, consider using "slice()" or "{}" +a = None # type: Annotated[int, 1:2] # E: Slice usage in type annotation is invalid +b = None # type: Dict[int, x:y] # E: Slice usage in type annotation is invalid +c = None # type: Dict[x:y] # E: Slice usage in type annotation is invalid [out] [case testCorrectSlicesInAnnotations39]