From 48bb89eb8ce1354c08b26b0a357bb9fb4814b791 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Wed, 6 Oct 2021 14:15:50 +0300 Subject: [PATCH 1/2] New error code for slices syntax, refs #10266 --- mypy/errorcodes.py | 1 + mypy/errors.py | 10 ++++++++++ mypy/fastparse.py | 14 ++++++++++---- test-data/unit/check-errorcodes.test | 21 +++++++++++++++++++++ 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/mypy/errorcodes.py b/mypy/errorcodes.py index d9e11a044a18d..3ae079f08fda4 100644 --- a/mypy/errorcodes.py +++ b/mypy/errorcodes.py @@ -135,6 +135,7 @@ def __str__(self) -> str: # Syntax errors are often blocking. SYNTAX: Final = ErrorCode("syntax", "Report syntax errors", "General") +SLICE_SYNTAX: Final = ErrorCode("slice-syntax", "Report slice syntax errors", "General") # This is a catch-all for remaining uncategorized errors. MISC: Final = ErrorCode("misc", "Miscellaneous other checks", "General") diff --git a/mypy/errors.py b/mypy/errors.py index 3a0e0e14d8b30..0917ac816af79 100644 --- a/mypy/errors.py +++ b/mypy/errors.py @@ -374,6 +374,16 @@ def add_error_info(self, info: ErrorInfo) -> None: return if file in self.ignored_files: return + if ( + not self.ignored_lines + and info.code + and self.is_error_code_enabled(info.code) is False + ): + # We also might want to ignore some errors during `fastparse`. + # At that moment `ignored_lines` might not be ready, + # so, we only check for specific error codes. + # For example, `Dict[{str: int}]` can be ignored this way. + return if info.only_once: if info.message in self.only_once_messages: return diff --git a/mypy/fastparse.py b/mypy/fastparse.py index a9c3bed9d5a76..ba5a8ebaa3956 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -1359,9 +1359,13 @@ def parent(self) -> Optional[AST]: return None return self.node_stack[-2] - def fail(self, msg: str, line: int, column: int) -> None: + def fail(self, msg: str, line: int, column: int, + blocker: bool = True, + code: Optional[codes.ErrorCode] = None) -> None: + if code is None: + code = codes.SYNTAX if self.errors: - self.errors.report(line, column, msg, blocker=True, code=codes.SYNTAX) + self.errors.report(line, column, msg, blocker=blocker, code=code) def note(self, msg: str, line: int, column: int) -> None: if self.errors: @@ -1562,12 +1566,14 @@ 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(INVALID_SLICE_ERROR, self.line, getattr(n, 'col_offset', -1)) + self.fail(INVALID_SLICE_ERROR, self.line, getattr(n, 'col_offset', -1), + blocker=False, code=codes.SLICE_SYNTAX) 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(INVALID_SLICE_ERROR, self.line, getattr(n, 'col_offset', -1)) + self.fail(INVALID_SLICE_ERROR, self.line, getattr(n, 'col_offset', -1), + blocker=False, code=codes.SLICE_SYNTAX) return AnyType(TypeOfAny.from_error) sliceval = n.slice.value diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test index 207c2d9b99c10..6a09a49081bd1 100644 --- a/test-data/unit/check-errorcodes.test +++ b/test-data/unit/check-errorcodes.test @@ -897,3 +897,24 @@ lst: List[int] = [] if lst: pass [builtins fixtures/list.pyi] + +[case testSliceAnnotatedErrorDisabled39] +# flags: --python-version 3.9 --disable-error-code slice-syntax +a: Annotated[int, 1:2] +b: Dict[int, x:y] +c: Dict[x:y] + +reveal_type(a) # N: Revealed type is "Any" +reveal_type(b) # N: Revealed type is "Any" +reveal_type(c) # N: Revealed type is "Any" + +[case testSliceAnnotatedErrorDisabled38] +# flags: --python-version 3.8 --disable-error-code slice-syntax + +a: Annotated[int, 1:2] +b: Dict[int, x:y] +c: Dict[x:y] + +reveal_type(a) # N: Revealed type is "Any" +reveal_type(b) # N: Revealed type is "Any" +reveal_type(c) # N: Revealed type is "Any" From ba83046809bba2398291e87d20366917b64dca4b Mon Sep 17 00:00:00 2001 From: sobolevn Date: Wed, 6 Oct 2021 14:34:59 +0300 Subject: [PATCH 2/2] Fixes tests --- test-data/unit/check-fastparse.test | 1 + 1 file changed, 1 insertion(+) diff --git a/test-data/unit/check-fastparse.test b/test-data/unit/check-fastparse.test index 03aa1e4c3214f..0766b46c68243 100644 --- a/test-data/unit/check-fastparse.test +++ b/test-data/unit/check-fastparse.test @@ -321,6 +321,7 @@ x @= 1 from typing import Dict x = None # type: Dict[x: y] +[builtins fixtures/dict.pyi] [out] main:3: error: Slice usage in type annotation is invalid