Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
39 changes: 38 additions & 1 deletion mypy/nativeparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,9 @@


class State:
def __init__(self, options: Options) -> None:
def __init__(self, options: Options, is_stub: bool = False) -> None:
self.options = options
self.is_stub = is_stub
self.errors: list[ParseError] = []
self.num_funcs = 0

Expand All @@ -180,6 +181,22 @@ def add_error(
{"line": line, "column": column, "message": message, "blocker": blocker, "code": code}
)

def check_min_version(
self, feature: str, min_version: tuple[int, int], line: int, column: int
) -> None:
"""Report a non blocker syntax error if the target Python feature is older than min_version."""
if self.is_stub:
return
if self.options.python_version < min_version:
self.add_error(
f"{feature} are only supported in Python "
f"{min_version[0]}.{min_version[1]} and greater",
line,
column,
blocker=False,
code="syntax",
)


def native_parse(
filename: str,
Expand Down Expand Up @@ -607,6 +624,13 @@ def read_parameters(state: State, data: ReadBuffer) -> tuple[list[Argument], boo
return arguments, has_ann


def check_type_param_defaults(
state: State, type_params: list[TypeParam], line: int, column: int
) -> None:
if any(p.default is not None for p in type_params):
state.check_min_version("Type parameter defaults", (3, 13), line, column)


def read_type_params(state: State, data: ReadBuffer) -> list[TypeParam]:
"""Read type parameters (PEP 695 generics)."""
type_params: list[TypeParam] = []
Expand Down Expand Up @@ -680,6 +704,9 @@ def read_func_def(state: State, data: ReadBuffer) -> FuncDef:
if is_async:
func_def.is_coroutine = True
read_loc(data, func_def)
if type_params:
state.check_min_version("Type parameter lists", (3, 12), func_def.line, func_def.column)
check_type_param_defaults(state, type_params, func_def.line, func_def.column)
if typ:
typ.line = func_def.line
typ.column = func_def.column
Expand Down Expand Up @@ -727,6 +754,9 @@ def read_class_def(state: State, data: ReadBuffer) -> ClassDef:
)
class_def.decorators = decorators
read_loc(data, class_def)
if type_params:
state.check_min_version("Type parameter lists", (3, 12), class_def.line, class_def.column)
check_type_param_defaults(state, type_params, class_def.line, class_def.column)
expect_end_tag(data)
return class_def

Expand Down Expand Up @@ -781,6 +811,8 @@ def read_type_alias_stmt(state: State, data: ReadBuffer) -> TypeAliasStmt:

stmt = TypeAliasStmt(name, type_params, lambda_expr)
read_loc(data, stmt)
state.check_min_version('"type" statements', (3, 12), stmt.line, stmt.column)
check_type_param_defaults(state, type_params, stmt.line, stmt.column)
expect_end_tag(data)
return stmt

Expand Down Expand Up @@ -832,6 +864,10 @@ def read_try_stmt(state: State, data: ReadBuffer) -> TryStmt:
stmt = TryStmt(body, vars_list, types_list, handlers, else_body, finally_body)
stmt.is_star = is_star
read_loc(data, stmt)
if is_star:
state.check_min_version("Exception groups", (3, 11), stmt.line, stmt.column)
if state.options.python_version < (3, 11):
stmt.is_star = False
expect_end_tag(data)
return stmt

Expand Down Expand Up @@ -1474,6 +1510,7 @@ def read_expression(state: State, data: ReadBuffer) -> Expression:
titems.append(s)
expr = TemplateStrExpr(titems)
read_loc(data, expr)
state.check_min_version("t-strings", (3, 14), expr.line, expr.column)
expect_end_tag(data)
return expr
elif tag == nodes.LAMBDA_EXPR:
Expand Down
2 changes: 1 addition & 1 deletion mypy/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def load_from_raw(
"""
from mypy.nativeparse import State, deserialize_imports, read_statements

state = State(options)
state = State(options, is_stub=fnam.endswith(".pyi"))
if imports_only:
defs = []
else:
Expand Down
Loading