-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement PEP 526 Variable Annotations Syntax #2131
Merged
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
32295da
Start PEP 526 implementation
ilevkivskyi be2ba3a
Backward compatibility for typed_ast
ilevkivskyi 1fb5787
Implement new semantics for None
ilevkivskyi 22ac4e8
sync parse with fastparse; prohibit var annotations before 3.6
ilevkivskyi b55b9ce
Fix failing tests; some polishing
ilevkivskyi 59ffb2c
Temporarily silence mypy complain; could be removed after typeshed up…
ilevkivskyi f02c9e7
Restore testing option for mypy
ilevkivskyi 2a16bc8
Merge to get newest typeshed submodule rev
ilevkivskyi 0e5bf09
Add unit tests for PEP 526 syntax
ilevkivskyi 0fca70f
Add one more unit test
ilevkivskyi 4a0a440
Imply strict-optional also in classes; fix problem with multiple None…
ilevkivskyi fe94105
Be very picky about what is protected against complains in strict opt…
ilevkivskyi 0f76f23
Restore mypy's testing option
ilevkivskyi aa6c5ba
Leave only PEP 526 stuff in
ilevkivskyi d2868cc
Backward compatible PEP 526 implementation + response to comments
ilevkivskyi 4807cc0
update for TypeCommentParseError
ilevkivskyi 11951d2
Merge remote-tracking branch 'upstream/master'
ilevkivskyi 7b05b49
Updates and response to comments
ilevkivskyi 7b46161
Remove redundant if
ilevkivskyi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,7 +14,7 @@ | |
UnaryExpr, FuncExpr, ComparisonExpr, | ||
StarExpr, YieldFromExpr, NonlocalDecl, DictionaryComprehension, | ||
SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, Argument, | ||
AwaitExpr, | ||
AwaitExpr, TempNode, | ||
ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_STAR2 | ||
) | ||
from mypy.types import ( | ||
|
@@ -403,16 +403,31 @@ def visit_Delete(self, n: ast35.Delete) -> Node: | |
else: | ||
return DelStmt(self.visit(n.targets[0])) | ||
|
||
# Assign(expr* targets, expr value, string? type_comment) | ||
# Assign(expr* targets, expr? value, string? type_comment, expr? annotation) | ||
@with_line | ||
def visit_Assign(self, n: ast35.Assign) -> Node: | ||
typ = None | ||
if n.type_comment: | ||
if hasattr(n, 'annotation') and n.annotation is not None: # type: ignore | ||
new_syntax = True | ||
else: | ||
new_syntax = False | ||
if new_syntax and self.pyversion < (3, 6): | ||
raise TypeCommentParseError('Variable annotation syntax is only ' | ||
'suppoted in Python 3.6, use type ' | ||
'comment instead', n.lineno, n.col_offset) | ||
# typed_ast prevents having both type_comment and annotation. | ||
if n.type_comment is not None: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you add a comment noting that typed_ast prevents there from being both a type comment and an annotation? |
||
typ = parse_type_comment(n.type_comment, n.lineno) | ||
|
||
return AssignmentStmt(self.visit_list(n.targets), | ||
self.visit(n.value), | ||
type=typ) | ||
elif new_syntax: | ||
typ = TypeConverter(line=n.lineno).visit(n.annotation) # type: ignore | ||
if n.value is None: # always allow 'x: int' | ||
rvalue = TempNode(AnyType()) # type: Node | ||
else: | ||
rvalue = self.visit(n.value) | ||
lvalues = self.visit_list(n.targets) | ||
return AssignmentStmt(lvalues, | ||
rvalue, | ||
type=typ, new_syntax=new_syntax) | ||
|
||
# AugAssign(expr target, operator op, expr value) | ||
@with_line | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
[case testNewSyntaxRequire36] | ||
# flags: --fast-parser --python-version 3.5 | ||
x: int = 5 # E: Variable annotation syntax is only suppoted in Python 3.6, use type comment instead | ||
[out] | ||
|
||
[case testNewSyntaxSyntaxError] | ||
# flags: --fast-parser --python-version 3.6 | ||
x: int: int # E: invalid syntax | ||
[out] | ||
|
||
[case testNewSyntaxBasics] | ||
# flags: --fast-parser --python-version 3.6 | ||
x: int | ||
x = 5 | ||
y: int = 5 | ||
|
||
a: str | ||
a = 5 # E: Incompatible types in assignment (expression has type "int", variable has type "str") | ||
b: str = 5 # E: Incompatible types in assignment (expression has type "int", variable has type "str") | ||
|
||
zzz: int | ||
zzz: str # E: Name 'zzz' already defined | ||
[out] | ||
|
||
[case testNewSyntaxWithDict] | ||
# flags: --fast-parser --python-version 3.6 | ||
from typing import Dict, Any | ||
|
||
d: Dict[int, str] = {} | ||
d[42] = 'ab' | ||
d[42] = 42 # E: Incompatible types in assignment (expression has type "int", target has type "str") | ||
d['ab'] = 'ab' # E: Invalid index type "str" for "dict" | ||
[builtins fixtures/dict.pyi] | ||
[out] | ||
|
||
[case testNewSyntaxWithRevealType] | ||
# flags: --fast-parser --python-version 3.6 | ||
from typing import Dict | ||
|
||
def tst_local(dct: Dict[int, T]) -> Dict[T, int]: | ||
ret: Dict[T, int] = {} | ||
return ret | ||
|
||
reveal_type(tst_local({1: 'a'})) # E: Revealed type is 'builtins.dict[builtins.str*, builtins.int]' | ||
[builtins fixtures/dict.pyi] | ||
[out] | ||
|
||
[case testNewSyntaxWithInstanceVars] | ||
# flags: --fast-parser --python-version 3.6 | ||
class TstInstance: | ||
a: str | ||
def __init__(self) -> None: | ||
self.x: int | ||
|
||
TstInstance().x = 5 | ||
TstInstance().x = 'ab' # E: Incompatible types in assignment (expression has type "str", variable has type "int") | ||
TstInstance().a = 5 # E: Incompatible types in assignment (expression has type "int", variable has type "str") | ||
TstInstance().a = 'ab' | ||
[out] | ||
|
||
[case testNewSyntaxWithClassVars] | ||
# flags: --fast-parser --strict-optional --python-version 3.6 | ||
class CCC: | ||
a: str = None # E: Incompatible types in assignment (expression has type None, variable has type "str") | ||
[out] | ||
main: note: In class "CCC": | ||
|
||
[case testNewSyntaxWithStrictOptional] | ||
# flags: --fast-parser --strict-optional --python-version 3.6 | ||
strict: int | ||
strict = None # E: Incompatible types in assignment (expression has type None, variable has type "int") | ||
strict2: int = None # E: Incompatible types in assignment (expression has type None, variable has type "int") | ||
[out] | ||
|
||
[case testNewSyntaxWithStrictOptionalFunctions] | ||
# flags: --fast-parser --strict-optional --python-version 3.6 | ||
def f() -> None: | ||
x: int | ||
x = None # E: Incompatible types in assignment (expression has type None, variable has type "int") | ||
[out] | ||
main: note: In function "f": | ||
|
||
[case testNewSyntaxWithStrictOptionalClasses] | ||
# flags: --fast-parser --strict-optional --python-version 3.6 | ||
class C: | ||
def meth(self) -> None: | ||
x: int = None # E: Incompatible types in assignment (expression has type None, variable has type "int") | ||
self.x: int = None # E: Incompatible types in assignment (expression has type None, variable has type "int") | ||
[out] | ||
main: note: In member "meth" of class "C": |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should display an error if there's a type comment and a type annotation.