Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ab3849b

Browse files
authored
Use native parse_type_string() (#21965)
Fixes #21515 I also fix one remainder from Python 2 age where we accepted bytes literals as forward references.
1 parent 0d30f08 commit ab3849b

4 files changed

Lines changed: 48 additions & 12 deletions

File tree

mypy/exprtotype.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
from collections.abc import Callable
66

7-
from mypy.fastparse import parse_type_string
87
from mypy.nodes import (
98
MISSING_FALLBACK,
109
BytesExpr,
@@ -30,6 +29,7 @@
3029
get_member_expr_fullname,
3130
)
3231
from mypy.options import Options
32+
from mypy.parse import parse_type_string
3333
from mypy.types import (
3434
ANNOTATED_TYPE_NAMES,
3535
AnyType,
@@ -221,9 +221,9 @@ def expr_to_unanalyzed_type(
221221
column=expr.column,
222222
)
223223
elif isinstance(expr, StrExpr):
224-
return parse_type_string(expr.value, "builtins.str", expr.line, expr.column)
224+
return parse_type_string(expr, options)
225225
elif isinstance(expr, BytesExpr):
226-
return parse_type_string(expr.value, "builtins.bytes", expr.line, expr.column)
226+
return RawExpressionType(expr.value, "builtins.bytes", expr.line, expr.column)
227227
elif isinstance(expr, UnaryExpr):
228228
typ = expr_to_unanalyzed_type(
229229
expr.expr, options, allow_new_syntax, lookup_qualified=lookup_qualified

mypy/nativeparse.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,23 @@ def native_parse(
254254
return node, errors, ignores
255255

256256

257+
def native_parse_type_string(
258+
expr_string: str, line: int, column: int, end_line: int, end_column: int, options: Options
259+
) -> ProperType:
260+
"""Try to parse a string literal as a type expression (i.e. resolve a forward reference).
261+
262+
If parsing fails, a RawExpressionType will be returned.
263+
"""
264+
ast_bytes = ast_serialize.parse_type_string(
265+
expr_string, (line, column, end_line, end_column), cache_version=5
266+
)
267+
state = State(options)
268+
data = ReadBuffer(ast_bytes)
269+
ret = read_type(state, data)
270+
assert isinstance(ret, ProperType)
271+
return ret
272+
273+
257274
def expect_end_tag(data: ReadBuffer) -> None:
258275
assert read_tag(data) == END_TAG
259276

mypy/parse.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
from mypy import errorcodes as codes
88
from mypy.cache import read_int
99
from mypy.errors import Errors
10-
from mypy.nodes import FileRawData, MypyFile, ParseError
10+
from mypy.nodes import FileRawData, MypyFile, ParseError, StrExpr
1111
from mypy.options import Options
12+
from mypy.types import ProperType
1213

1314

1415
def parse(
@@ -115,3 +116,20 @@ def report_parse_error(error: ParseError, errors: Errors) -> None:
115116
# Fallback to [syntax] for backwards compatibility.
116117
error_code = codes.error_codes.get(error_code) or codes.SYNTAX
117118
errors.report(error["line"], error["column"], message, blocker=is_blocker, code=error_code)
119+
120+
121+
def parse_type_string(expr: StrExpr, options: Options) -> ProperType:
122+
if options.native_parser:
123+
import mypy.nativeparse
124+
125+
return mypy.nativeparse.native_parse_type_string(
126+
expr.value,
127+
expr.line,
128+
expr.column,
129+
expr.end_line or expr.line,
130+
expr.end_column or expr.column,
131+
options,
132+
)
133+
import mypy.fastparse
134+
135+
return mypy.fastparse.parse_type_string(expr.value, "builtins.str", expr.line, expr.column)

test-data/unit/check-literal.test

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ accepts_bytes(c_alias)
224224
[builtins fixtures/tuple.pyi]
225225
[out]
226226

227-
[case testLiteralMixingUnicodeAndBytesPython3ForwardStrings_no_native_parse]
227+
[case testLiteralMixingUnicodeAndBytesPython3ForwardStrings]
228228
from typing import Literal, TypeVar, Generic
229229

230230
a_unicode_wrapper: u"Literal[u'foo']"
@@ -235,7 +235,7 @@ a_str_wrapper: "Literal[u'foo']"
235235
b_str_wrapper: "Literal['foo']"
236236
c_str_wrapper: "Literal[b'foo']"
237237

238-
# In Python 3, forward references MUST be str, not bytes
238+
# In Python 3, forward references MUST be str, not bytes.
239239
a_bytes_wrapper: b"Literal[u'foo']" # E: Invalid type comment or annotation
240240
b_bytes_wrapper: b"Literal['foo']" # E: Invalid type comment or annotation
241241
c_bytes_wrapper: b"Literal[b'foo']" # E: Invalid type comment or annotation
@@ -265,9 +265,10 @@ a_str_wrapper_alias: AStrWrapperAlias
265265
b_str_wrapper_alias: BStrWrapperAlias
266266
c_str_wrapper_alias: CStrWrapperAlias
267267

268-
ABytesWrapperAlias = Wrap[b"Literal[u'foo']"]
269-
BBytesWrapperAlias = Wrap[b"Literal['foo']"]
270-
CBytesWrapperAlias = Wrap[b"Literal[b'foo']"]
268+
# Bytes literals are not valid as forward references.
269+
ABytesWrapperAlias = Wrap[b"Literal[u'foo']"] # E: Invalid type comment or annotation
270+
BBytesWrapperAlias = Wrap[b"Literal['foo']"] # E: Invalid type comment or annotation
271+
CBytesWrapperAlias = Wrap[b"Literal[b'foo']"] # E: Invalid type comment or annotation
271272
a_bytes_wrapper_alias: ABytesWrapperAlias
272273
b_bytes_wrapper_alias: BBytesWrapperAlias
273274
c_bytes_wrapper_alias: CBytesWrapperAlias
@@ -282,9 +283,9 @@ reveal_type(a_str_wrapper_alias) # N: Revealed type is "__main__.Wrap[Liter
282283
reveal_type(b_str_wrapper_alias) # N: Revealed type is "__main__.Wrap[Literal['foo']]"
283284
reveal_type(c_str_wrapper_alias) # N: Revealed type is "__main__.Wrap[Literal[b'foo']]"
284285

285-
reveal_type(a_bytes_wrapper_alias) # N: Revealed type is "__main__.Wrap[Literal['foo']]"
286-
reveal_type(b_bytes_wrapper_alias) # N: Revealed type is "__main__.Wrap[Literal['foo']]"
287-
reveal_type(c_bytes_wrapper_alias) # N: Revealed type is "__main__.Wrap[Literal[b'foo']]"
286+
reveal_type(a_bytes_wrapper_alias) # N: Revealed type is "__main__.Wrap[Any]"
287+
reveal_type(b_bytes_wrapper_alias) # N: Revealed type is "__main__.Wrap[Any]"
288+
reveal_type(c_bytes_wrapper_alias) # N: Revealed type is "__main__.Wrap[Any]"
288289
[builtins fixtures/tuple.pyi]
289290
[out]
290291

0 commit comments

Comments
 (0)