diff --git a/mypy/backports.py b/mypy/backports.py deleted file mode 100644 index 2a6397ff7316..000000000000 --- a/mypy/backports.py +++ /dev/null @@ -1,20 +0,0 @@ -import sys -from contextlib import contextmanager -from typing import Iterator - -if sys.version_info < (3, 6): - from collections import OrderedDict as OrderedDict # noqa: F401 -else: - # OrderedDict is kind of slow, so for most of our uses in Python 3.6 - # and later we'd rather just use dict - OrderedDict = dict - - -if sys.version_info < (3, 7): - - @contextmanager - def nullcontext() -> Iterator[None]: - yield - -else: - from contextlib import nullcontext as nullcontext # noqa: F401 diff --git a/mypy/build.py b/mypy/build.py index 95440d0db2e7..385fc83f7b11 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -2336,8 +2336,9 @@ def type_check_second_pass(self) -> bool: return False t0 = time_ref() with self.wrap_context(): - return self.type_checker().check_second_pass() + result = self.type_checker().check_second_pass() self.time_spent_us += time_spent_us(t0) + return result def finish_passes(self) -> None: assert self.tree is not None, "Internal error: method must be called on parsed file only" diff --git a/mypy/checker.py b/mypy/checker.py index a52cc7271537..a01098bad96a 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -3,7 +3,7 @@ import fnmatch import itertools from collections import defaultdict -from contextlib import contextmanager +from contextlib import contextmanager, nullcontext from typing import ( AbstractSet, Any, @@ -29,7 +29,6 @@ import mypy.checkexpr from mypy import errorcodes as codes, message_registry, nodes, operators -from mypy.backports import nullcontext from mypy.binder import ConditionalTypeBinder, get_declaration from mypy.checkmember import ( MemberContext, diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 0753ee80c113..c445b1a9b714 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -10,7 +10,6 @@ import mypy.errorcodes as codes from mypy import applytype, erasetype, join, message_registry, nodes, operators, types from mypy.argmap import ArgTypeExpander, map_actuals_to_formals, map_formals_to_actuals -from mypy.backports import OrderedDict from mypy.checkmember import analyze_member_access, type_object_type from mypy.checkstrformat import StringFormatterChecker from mypy.erasetype import erase_type, remove_instance_last_known_values, replace_meta_vars @@ -624,7 +623,7 @@ def check_typeddict_call( item_names = cast(List[str], arg_names) item_args = args return self.check_typeddict_call_with_kwargs( - callee, OrderedDict(zip(item_names, item_args)), context + callee, dict(zip(item_names, item_args)), context ) if len(args) == 1 and arg_kinds[0] == ARG_POS: @@ -638,14 +637,12 @@ def check_typeddict_call( if len(args) == 0: # ex: EmptyDict() - return self.check_typeddict_call_with_kwargs(callee, OrderedDict(), context) + return self.check_typeddict_call_with_kwargs(callee, {}, context) self.chk.fail(message_registry.INVALID_TYPEDDICT_ARGS, context) return AnyType(TypeOfAny.from_error) - def validate_typeddict_kwargs( - self, kwargs: DictExpr - ) -> "Optional[OrderedDict[str, Expression]]": + def validate_typeddict_kwargs(self, kwargs: DictExpr) -> "Optional[Dict[str, Expression]]": item_args = [item[1] for item in kwargs.items] item_names = [] # List[str] @@ -662,7 +659,7 @@ def validate_typeddict_kwargs( return None else: item_names.append(literal_value) - return OrderedDict(zip(item_names, item_args)) + return dict(zip(item_names, item_args)) def match_typeddict_call_with_dict( self, callee: TypedDictType, kwargs: DictExpr, context: Context @@ -685,7 +682,7 @@ def check_typeddict_call_with_dict( return AnyType(TypeOfAny.from_error) def check_typeddict_call_with_kwargs( - self, callee: TypedDictType, kwargs: "OrderedDict[str, Expression]", context: Context + self, callee: TypedDictType, kwargs: Dict[str, Expression], context: Context ) -> Type: if not (callee.required_keys <= set(kwargs.keys()) <= set(callee.items.keys())): expected_keys = [ @@ -3137,10 +3134,7 @@ def check_op( base_type = get_proper_type(base_type) if isinstance(base_type, UnionType): left_variants = [ - item - for item in flatten_nested_unions( - base_type.relevant_items(), handle_type_alias_type=True - ) + item for item in flatten_nested_unions(base_type.relevant_items()) ] right_type = self.accept(arg) @@ -3184,9 +3178,7 @@ def check_op( if isinstance(right_type, UnionType): right_variants = [ (item, TempNode(item, context=context)) - for item in flatten_nested_unions( - right_type.relevant_items(), handle_type_alias_type=True - ) + for item in flatten_nested_unions(right_type.relevant_items()) ] all_results = [] diff --git a/mypy/checkpattern.py b/mypy/checkpattern.py index a6390367d6a7..cbc2d89b8f9e 100644 --- a/mypy/checkpattern.py +++ b/mypy/checkpattern.py @@ -621,8 +621,6 @@ def generate_types_from_names(self, type_names: List[str]) -> List[Type]: # Some built in types are not defined in all test cases if not name.startswith("builtins."): raise e - pass - return types def update_type_map( diff --git a/mypy/errors.py b/mypy/errors.py index 00421040a9c9..1788f89d69ca 100644 --- a/mypy/errors.py +++ b/mypy/errors.py @@ -7,7 +7,6 @@ from typing_extensions import Final, Literal, NoReturn from mypy import errorcodes as codes -from mypy.backports import OrderedDict from mypy.errorcodes import IMPORT, ErrorCode from mypy.message_registry import ErrorMessage from mypy.options import Options @@ -154,7 +153,8 @@ def __enter__(self) -> "ErrorWatcher": return self def __exit__(self, exc_type: object, exc_val: object, exc_tb: object) -> Literal[False]: - assert self == self.errors._watchers.pop() + last = self.errors._watchers.pop() + assert last == self return False def on_error(self, file: str, info: ErrorInfo) -> bool: @@ -279,11 +279,11 @@ def __init__( self.initialize() def initialize(self) -> None: - self.error_info_map = OrderedDict() + self.error_info_map = {} self.flushed_files = set() self.import_ctx = [] self.function_or_member = [None] - self.ignored_lines = OrderedDict() + self.ignored_lines = {} self.used_ignored_lines = defaultdict(lambda: defaultdict(list)) self.ignored_files = set() self.only_once_messages = set() @@ -606,43 +606,43 @@ def clear_errors_in_targets(self, path: str, targets: Set[str]) -> None: self.has_blockers.remove(path) def generate_unused_ignore_errors(self, file: str) -> None: + if is_typeshed_file(file) or file in self.ignored_files: + return ignored_lines = self.ignored_lines[file] - if not is_typeshed_file(file) and file not in self.ignored_files: - ignored_lines = self.ignored_lines[file] - used_ignored_lines = self.used_ignored_lines[file] - for line, ignored_codes in ignored_lines.items(): - used_ignored_codes = used_ignored_lines[line] - unused_ignored_codes = set(ignored_codes) - set(used_ignored_codes) - # `ignore` is used - if len(ignored_codes) == 0 and len(used_ignored_codes) > 0: - continue - # All codes appearing in `ignore[...]` are used - if len(ignored_codes) > 0 and len(unused_ignored_codes) == 0: - continue - # Display detail only when `ignore[...]` specifies more than one error code - unused_codes_message = "" - if len(ignored_codes) > 1 and len(unused_ignored_codes) > 0: - unused_codes_message = f"[{', '.join(sorted(unused_ignored_codes))}]" - message = f'Unused "type: ignore{unused_codes_message}" comment' - # Don't use report since add_error_info will ignore the error! - info = ErrorInfo( - self.import_context(), - file, - self.current_module(), - None, - None, - line, - -1, - line, - -1, - "error", - message, - None, - False, - False, - False, - ) - self._add_error_info(file, info) + used_ignored_lines = self.used_ignored_lines[file] + for line, ignored_codes in ignored_lines.items(): + used_ignored_codes = used_ignored_lines[line] + unused_ignored_codes = set(ignored_codes) - set(used_ignored_codes) + # `ignore` is used + if len(ignored_codes) == 0 and len(used_ignored_codes) > 0: + continue + # All codes appearing in `ignore[...]` are used + if len(ignored_codes) > 0 and len(unused_ignored_codes) == 0: + continue + # Display detail only when `ignore[...]` specifies more than one error code + unused_codes_message = "" + if len(ignored_codes) > 1 and len(unused_ignored_codes) > 0: + unused_codes_message = f"[{', '.join(sorted(unused_ignored_codes))}]" + message = f'Unused "type: ignore{unused_codes_message}" comment' + # Don't use report since add_error_info will ignore the error! + info = ErrorInfo( + self.import_context(), + file, + self.current_module(), + None, + None, + line, + -1, + line, + -1, + "error", + message, + None, + False, + False, + False, + ) + self._add_error_info(file, info) def generate_ignore_without_code_errors( self, file: str, is_warning_unused_ignores: bool diff --git a/mypy/inspections.py b/mypy/inspections.py index d2c090351b5b..97ce315497fa 100644 --- a/mypy/inspections.py +++ b/mypy/inspections.py @@ -122,7 +122,6 @@ def find_module_by_fullname(fullname: str, modules: Dict[str, State]) -> Optiona mod = modules.get(head) if mod is not None: return mod - return None class SearchVisitor(ExtendedTraverserVisitor): diff --git a/mypy/join.py b/mypy/join.py index 31f31ed88714..6a60cb0720e1 100644 --- a/mypy/join.py +++ b/mypy/join.py @@ -3,7 +3,6 @@ from typing import List, Optional, Tuple import mypy.typeops -from mypy.backports import OrderedDict from mypy.maptype import map_instance_to_supertype from mypy.nodes import CONTRAVARIANT, COVARIANT, INVARIANT from mypy.state import state @@ -447,16 +446,14 @@ def visit_tuple_type(self, t: TupleType) -> ProperType: def visit_typeddict_type(self, t: TypedDictType) -> ProperType: if isinstance(self.s, TypedDictType): - items = OrderedDict( - [ - (item_name, s_item_type) - for (item_name, s_item_type, t_item_type) in self.s.zip(t) - if ( - is_equivalent(s_item_type, t_item_type) - and (item_name in t.required_keys) == (item_name in self.s.required_keys) - ) - ] - ) + items = { + item_name: s_item_type + for (item_name, s_item_type, t_item_type) in self.s.zip(t) + if ( + is_equivalent(s_item_type, t_item_type) + and (item_name in t.required_keys) == (item_name in self.s.required_keys) + ) + } fallback = self.s.create_anonymous_fallback() # We need to filter by items.keys() since some required keys present in both t and # self.s might be missing from the join if the types are incompatible. diff --git a/mypy/main.py b/mypy/main.py index de58cff404ea..3a434b311d25 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -483,7 +483,7 @@ def add_invertible_flag( flag, action="store_false" if default else "store_true", dest=dest, help=help ) dest = arg.dest - arg = group.add_argument( + group.add_argument( inverse, action="store_true" if default else "store_false", dest=dest, diff --git a/mypy/meet.py b/mypy/meet.py index e3fc73033821..1ea5c49c0680 100644 --- a/mypy/meet.py +++ b/mypy/meet.py @@ -1,7 +1,6 @@ from typing import Callable, List, Optional, Tuple from mypy import join -from mypy.backports import OrderedDict from mypy.erasetype import erase_type from mypy.maptype import map_instance_to_supertype from mypy.state import state @@ -776,7 +775,7 @@ def visit_typeddict_type(self, t: TypedDictType) -> ProperType: # at least one of s_item_type and t_item_type is not None assert t_item_type is not None item_list.append((item_name, t_item_type)) - items = OrderedDict(item_list) + items = dict(item_list) fallback = self.s.create_anonymous_fallback() required_keys = t.required_keys | self.s.required_keys return TypedDictType(items, required_keys, fallback) diff --git a/mypy/messages.py b/mypy/messages.py index 629d04c85dc5..b0dff20fc8b2 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -30,7 +30,6 @@ from typing_extensions import Final from mypy import errorcodes as codes, message_registry -from mypy.backports import OrderedDict from mypy.erasetype import erase_type from mypy.errorcodes import ErrorCode from mypy.errors import ErrorInfo, Errors, ErrorWatcher @@ -1511,7 +1510,7 @@ def reveal_type(self, typ: Type, context: Context) -> None: def reveal_locals(self, type_map: Dict[str, Optional[Type]], context: Context) -> None: # To ensure that the output is predictable on Python < 3.6, # use an ordered dictionary sorted by variable name - sorted_locals = OrderedDict(sorted(type_map.items(), key=lambda t: t[0])) + sorted_locals = dict(sorted(type_map.items(), key=lambda t: t[0])) if sorted_locals: self.note("Revealed local types are:", context) for k, v in sorted_locals.items(): diff --git a/mypy/mro.py b/mypy/mro.py index 3c29013d62c9..e4e8eecfb97e 100644 --- a/mypy/mro.py +++ b/mypy/mro.py @@ -30,9 +30,8 @@ def linearize_hierarchy( return info.mro bases = info.direct_base_classes() if not bases and info.fullname != "builtins.object" and obj_type is not None: - # Second pass in import cycle, add a dummy `object` base class, + # Probably an error, add a dummy `object` base class, # otherwise MRO calculation may spuriously fail. - # MRO will be re-calculated for real in the third pass. bases = [obj_type().type] lin_bases = [] for base in bases: diff --git a/mypy/nodes.py b/mypy/nodes.py index e1230f802cf6..633b3a8a3d2b 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -23,7 +23,6 @@ from typing_extensions import TYPE_CHECKING, DefaultDict, Final, TypeAlias as _TypeAlias import mypy.strconv -from mypy.backports import OrderedDict from mypy.bogus_type import Bogus from mypy.util import short_type from mypy.visitor import ExpressionVisitor, NodeVisitor, StatementVisitor @@ -1092,7 +1091,7 @@ class ClassDef(Statement): info: "TypeInfo" # Related TypeInfo metaclass: Optional[Expression] decorators: List[Expression] - keywords: "OrderedDict[str, Expression]" + keywords: Dict[str, Expression] analyzed: Optional[Expression] has_incompatible_baseclass: bool @@ -1115,7 +1114,7 @@ def __init__( self.info = CLASSDEF_NO_INFO self.metaclass = metaclass self.decorators = [] - self.keywords = OrderedDict(keywords or []) + self.keywords = dict(keywords) if keywords else {} self.analyzed = None self.has_incompatible_baseclass = False # Used for error reporting (to keep backwad compatibility with pre-3.8) @@ -2704,7 +2703,7 @@ class is generic then it will be a type constructor of higher kind. # in corresponding column. This matrix typically starts filled with all 1's and # a typechecker tries to "disprove" every subtyping relation using atomic (or nominal) types. # However, we don't want to keep this huge global state. Instead, we keep the subtype - # information in the form of list of pairs (subtype, supertype) shared by all 'Instance's + # information in the form of list of pairs (subtype, supertype) shared by all Instances # with given supertype's TypeInfo. When we enter a subtype check we push a pair in this list # thus assuming that we started with 1 in corresponding matrix element. Such algorithm allows # to treat recursive and mutually recursive protocols and other kinds of complex situations. @@ -2715,7 +2714,7 @@ class is generic then it will be a type constructor of higher kind. assuming: List[Tuple["mypy.types.Instance", "mypy.types.Instance"]] assuming_proper: List[Tuple["mypy.types.Instance", "mypy.types.Instance"]] # Ditto for temporary 'inferring' stack of recursive constraint inference. - # It contains Instance's of protocol types that appeared as an argument to + # It contains Instances of protocol types that appeared as an argument to # constraints.infer_constraints(). We need 'inferring' to avoid infinite recursion for # recursive and mutually recursive protocols. # @@ -3197,7 +3196,7 @@ def f(x: B[T]) -> T: ... # without T, Any would be used here Note: the fact that we support aliases like `A = List` means that the target type will be initially an instance type with wrong number of type arguments. - Such instances are all fixed in the third pass of semantic analyzis. + Such instances are all fixed either during or after main semantic analysis passes. We therefore store the difference between `List` and `List[Any]` rvalues (targets) using the `no_args` flag. See also TypeAliasExpr.no_args. @@ -3212,7 +3211,7 @@ def f(x: B[T]) -> T: ... # without T, Any would be used here are internally stored using `builtins.list` (because `typing.List` is itself an alias), while the second cannot be subscripted because of Python runtime limitation. - line and column: Line an column on the original alias definition. + line and column: Line and column on the original alias definition. eager: If True, immediately expand alias when referred to (useful for aliases within functions that can't be looked up from the symbol table) """ @@ -3333,7 +3332,7 @@ class C(Sequence[C]): ... Attributes: - fullname: Full name of of the PlaceholderNode. + fullname: Full name of the PlaceholderNode. node: AST node that contains the definition that caused this to be created. This is useful for tracking order of incomplete definitions and for debugging. diff --git a/mypy/options.py b/mypy/options.py index 4d31e52367db..2f207702c439 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -6,7 +6,6 @@ from typing_extensions import TYPE_CHECKING, Final from mypy import defaults -from mypy.backports import OrderedDict from mypy.util import get_class_descriptors, replace_object_state if TYPE_CHECKING: @@ -255,7 +254,7 @@ def __init__(self) -> None: self.plugins: List[str] = [] # Per-module options (raw) - self.per_module_options: OrderedDict[str, Dict[str, object]] = OrderedDict() + self.per_module_options: Dict[str, Dict[str, object]] = {} self._glob_options: List[Tuple[str, Pattern[str]]] = [] self.unused_configs: Set[str] = set() diff --git a/mypy/plugins/attrs.py b/mypy/plugins/attrs.py index 60098cc95201..6fe2529331ed 100644 --- a/mypy/plugins/attrs.py +++ b/mypy/plugins/attrs.py @@ -5,7 +5,6 @@ from typing_extensions import Final import mypy.plugin # To avoid circular imports. -from mypy.backports import OrderedDict from mypy.exprtotype import TypeTranslationError, expr_to_unanalyzed_type from mypy.nodes import ( ARG_NAMED, @@ -354,7 +353,7 @@ def _analyze_class( auto_attribs=None means we'll detect which mode to use. kw_only=True means that all attributes created here will be keyword only args in __init__. """ - own_attrs: OrderedDict[str, Attribute] = OrderedDict() + own_attrs: Dict[str, Attribute] = {} if auto_attribs is None: auto_attribs = _detect_auto_attribs(ctx) diff --git a/mypy/scope.py b/mypy/scope.py index cf7e0514ebe8..cc5ce6a704a8 100644 --- a/mypy/scope.py +++ b/mypy/scope.py @@ -3,12 +3,11 @@ TODO: Use everywhere where we track targets, including in mypy.errors. """ -from contextlib import contextmanager +from contextlib import contextmanager, nullcontext from typing import Iterator, List, Optional, Tuple from typing_extensions import TypeAlias as _TypeAlias -from mypy.backports import nullcontext from mypy.nodes import FuncBase, TypeInfo SavedScope: _TypeAlias = Tuple[str, Optional[TypeInfo], Optional[FuncBase]] diff --git a/mypy/semanal.py b/mypy/semanal.py index 974ca5a69864..00b480caa8b8 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -1861,9 +1861,7 @@ def calculate_class_mro( ) -> None: """Calculate method resolution order for a class. - `obj_type` may be omitted in the third pass when all classes are already analyzed. - It exists just to fill in empty base class list during second pass in case of - an import cycle. + `obj_type` exists just to fill in empty base class list in case of an error. """ try: calculate_mro(defn.info, obj_type) @@ -3779,7 +3777,7 @@ def basic_new_typeinfo(self, name: str, basetype_or_fallback: Instance, line: in class_def.info = info mro = basetype_or_fallback.type.mro if not mro: - # Forward reference, MRO should be recalculated in third pass. + # Probably an error, we should not crash so generate something meaningful. mro = [basetype_or_fallback.type, self.object_type().type] info.mro = [info] + mro info.bases = [basetype_or_fallback] @@ -4873,10 +4871,9 @@ def lookup( for table in reversed(self.locals[:-1]): if table is not None and name in table: return table[name] - else: - if not suppress_errors: - self.name_not_defined(name, ctx) - return None + if not suppress_errors: + self.name_not_defined(name, ctx) + return None # 2. Class attributes (if within class definition) if self.type and not self.is_func_scope() and name in self.type.names: node = self.type.names[name] @@ -5234,8 +5231,8 @@ def add_symbol_skip_local(self, name: str, node: SymbolNode) -> None: This method can be used to add such classes to an enclosing, serialized symbol table. """ - # TODO: currently this is only used by named tuples. Use this method - # also by typed dicts and normal classes, see issue #6422. + # TODO: currently this is only used by named tuples and typed dicts. + # Use this method also by normal classes, see issue #6422. if self.type is not None: names = self.type.names kind = MDEF diff --git a/mypy/semanal_main.py b/mypy/semanal_main.py index e593960717b0..e06a95674fcc 100644 --- a/mypy/semanal_main.py +++ b/mypy/semanal_main.py @@ -24,13 +24,13 @@ will be incomplete. """ +from contextlib import nullcontext from typing import Callable, List, Optional, Tuple, Union from typing_extensions import TYPE_CHECKING, Final, TypeAlias as _TypeAlias import mypy.build import mypy.state -from mypy.backports import nullcontext from mypy.checker import FineGrainedDeferredNode from mypy.errors import Errors from mypy.nodes import Decorator, FuncDef, MypyFile, OverloadedFuncDef, TypeInfo, Var diff --git a/mypy/semanal_typeddict.py b/mypy/semanal_typeddict.py index 307690dc86fd..f0222676e3cc 100644 --- a/mypy/semanal_typeddict.py +++ b/mypy/semanal_typeddict.py @@ -5,7 +5,6 @@ from typing_extensions import Final from mypy import errorcodes as codes -from mypy.backports import OrderedDict from mypy.errorcodes import ErrorCode from mypy.exprtotype import TypeTranslationError, expr_to_unanalyzed_type from mypy.messages import MessageBuilder @@ -386,9 +385,7 @@ def build_typeddict_typeinfo( ) assert fallback is not None info = self.api.basic_new_typeinfo(name, fallback, line) - info.typeddict_type = TypedDictType( - OrderedDict(zip(items, types)), required_keys, fallback - ) + info.typeddict_type = TypedDictType(dict(zip(items, types)), required_keys, fallback) return info # Helpers diff --git a/mypy/server/aststrip.py b/mypy/server/aststrip.py index 936765160e92..516a78c6c21c 100644 --- a/mypy/server/aststrip.py +++ b/mypy/server/aststrip.py @@ -31,10 +31,9 @@ even though some identities are preserved. """ -import contextlib +from contextlib import contextmanager, nullcontext from typing import Dict, Iterator, Optional, Tuple, Union -from mypy.backports import nullcontext from mypy.nodes import ( CLASSDEF_NO_INFO, AssignmentStmt, @@ -250,7 +249,7 @@ def process_lvalue_in_method(self, lvalue: Node) -> None: elif isinstance(lvalue, StarExpr): self.process_lvalue_in_method(lvalue.expr) - @contextlib.contextmanager + @contextmanager def enter_class(self, info: TypeInfo) -> Iterator[None]: old_type = self.type old_is_class_body = self.is_class_body @@ -260,7 +259,7 @@ def enter_class(self, info: TypeInfo) -> Iterator[None]: self.type = old_type self.is_class_body = old_is_class_body - @contextlib.contextmanager + @contextmanager def enter_method(self, info: TypeInfo) -> Iterator[None]: old_type = self.type old_is_class_body = self.is_class_body diff --git a/mypy/suggestions.py b/mypy/suggestions.py index 1d5533e8a448..8b6a2332aff0 100644 --- a/mypy/suggestions.py +++ b/mypy/suggestions.py @@ -326,7 +326,7 @@ def get_trivial_type(self, fdef: FuncDef) -> CallableType: # since they need some special treatment (specifically, # constraint generation ignores them.) return CallableType( - [AnyType(TypeOfAny.suggestion_engine) for a in fdef.arg_kinds], + [AnyType(TypeOfAny.suggestion_engine) for _ in fdef.arg_kinds], fdef.arg_kinds, fdef.arg_names, AnyType(TypeOfAny.suggestion_engine), diff --git a/mypy/type_visitor.py b/mypy/type_visitor.py index 774488b7ac3f..3e01cfead216 100644 --- a/mypy/type_visitor.py +++ b/mypy/type_visitor.py @@ -16,10 +16,6 @@ from mypy_extensions import mypyc_attr, trait -from mypy.backports import OrderedDict - -T = TypeVar("T") - from mypy.types import ( AnyType, CallableArgument, @@ -53,6 +49,8 @@ get_proper_type, ) +T = TypeVar("T") + @trait @mypyc_attr(allow_interpreted_subclasses=True) @@ -254,9 +252,7 @@ def visit_tuple_type(self, t: TupleType) -> Type: ) def visit_typeddict_type(self, t: TypedDictType) -> Type: - items = OrderedDict( - [(item_name, item_type.accept(self)) for (item_name, item_type) in t.items.items()] - ) + items = {item_name: item_type.accept(self) for (item_name, item_type) in t.items.items()} return TypedDictType( items, t.required_keys, diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 9e068a39671d..ebec16e5e171 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -8,7 +8,6 @@ from typing_extensions import Final, Protocol from mypy import errorcodes as codes, message_registry, nodes -from mypy.backports import OrderedDict from mypy.errorcodes import ErrorCode from mypy.exprtotype import TypeTranslationError, expr_to_unanalyzed_type from mypy.messages import MessageBuilder, format_type_bare, quote_type_string @@ -910,9 +909,9 @@ def visit_tuple_type(self, t: TupleType) -> Type: return TupleType(self.anal_array(t.items), fallback, t.line) def visit_typeddict_type(self, t: TypedDictType) -> Type: - items = OrderedDict( - [(item_name, self.anal_type(item_type)) for (item_name, item_type) in t.items.items()] - ) + items = { + item_name: self.anal_type(item_type) for (item_name, item_type) in t.items.items() + } return TypedDictType(items, set(t.required_keys), t.fallback) def visit_raw_expression_type(self, t: RawExpressionType) -> Type: diff --git a/mypy/typeops.py b/mypy/typeops.py index ef3ec1de24c9..f6e5490de0ae 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -449,7 +449,7 @@ def make_simplified_union( to_union(). """ # Step 1: expand all nested unions - items = flatten_nested_unions(items, handle_type_alias_type=True) + items = flatten_nested_unions(items) # Step 2: remove redundant unions simplified_set: Sequence[Type] = _remove_redundant_union_items(items, keep_erased) diff --git a/mypy/types.py b/mypy/types.py index 7487654c4251..60e33df40fbb 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -20,7 +20,6 @@ from typing_extensions import TYPE_CHECKING, ClassVar, Final, TypeAlias as _TypeAlias, overload import mypy.nodes -from mypy.backports import OrderedDict from mypy.bogus_type import Bogus from mypy.nodes import ( ARG_POS, @@ -2152,13 +2151,13 @@ class TypedDictType(ProperType): __slots__ = ("items", "required_keys", "fallback") - items: "OrderedDict[str, Type]" # item_name -> item_type + items: Dict[str, Type] # item_name -> item_type required_keys: Set[str] fallback: Instance def __init__( self, - items: "OrderedDict[str, Type]", + items: Dict[str, Type], required_keys: Set[str], fallback: Instance, line: int = -1, @@ -2200,7 +2199,7 @@ def serialize(self) -> JsonDict: def deserialize(cls, data: JsonDict) -> "TypedDictType": assert data[".class"] == "TypedDictType" return TypedDictType( - OrderedDict([(n, deserialize_type(t)) for (n, t) in data["items"]]), + {n: deserialize_type(t) for (n, t) in data["items"]}, set(data["required_keys"]), Instance.deserialize(data["fallback"]), ) @@ -2226,7 +2225,7 @@ def copy_modified( if item_types is None: items = self.items else: - items = OrderedDict(zip(self.items, item_types)) + items = dict(zip(self.items, item_types)) if required_keys is None: required_keys = self.required_keys return TypedDictType(items, required_keys, fallback, self.line, self.column) @@ -2465,7 +2464,9 @@ def __init__( uses_pep604_syntax: bool = False, ) -> None: super().__init__(line, column) - self.items = flatten_nested_unions(items) + # We must keep this false to avoid crashes during semantic analysis. + # TODO: maybe switch this to True during type-checking pass? + self.items = flatten_nested_unions(items, handle_type_alias_type=False) self.can_be_true = any(item.can_be_true for item in items) self.can_be_false = any(item.can_be_false for item in items) # is_evaluated should be set to false for type comments and string literals @@ -3160,12 +3161,9 @@ def has_recursive_types(typ: Type) -> bool: def flatten_nested_unions( - types: Iterable[Type], handle_type_alias_type: bool = False + types: Iterable[Type], handle_type_alias_type: bool = True ) -> List[Type]: """Flatten nested unions in a type list.""" - # This and similar functions on unions can cause infinite recursion - # if passed a "pathological" alias like A = Union[int, A] or similar. - # TODO: ban such aliases in semantic analyzer. flat_items: List[Type] = [] # TODO: avoid duplicate types in unions (e.g. using hash) for t in types: @@ -3223,8 +3221,7 @@ def bad_type_type_item(item: Type) -> bool: return True if isinstance(item, UnionType): return any( - isinstance(get_proper_type(i), TypeType) - for i in flatten_nested_unions(item.items, handle_type_alias_type=True) + isinstance(get_proper_type(i), TypeType) for i in flatten_nested_unions(item.items) ) return False diff --git a/mypyc/codegen/emit.py b/mypyc/codegen/emit.py index 0c9f708472d0..a43249ec455c 100644 --- a/mypyc/codegen/emit.py +++ b/mypyc/codegen/emit.py @@ -5,7 +5,6 @@ from typing_extensions import Final -from mypy.backports import OrderedDict from mypyc.codegen.literals import Literals from mypyc.common import ( ATTR_PREFIX, @@ -117,7 +116,7 @@ def __init__( # A map of a C identifier to whatever the C identifier declares. Currently this is # used for declaring structs and the key corresponds to the name of the struct. # The declaration contains the body of the struct. - self.declarations: Dict[str, HeaderDeclaration] = OrderedDict() + self.declarations: Dict[str, HeaderDeclaration] = {} self.literals = Literals() diff --git a/mypyc/codegen/emitclass.py b/mypyc/codegen/emitclass.py index 4666443800a6..4cd420b29aa5 100644 --- a/mypyc/codegen/emitclass.py +++ b/mypyc/codegen/emitclass.py @@ -2,7 +2,6 @@ from typing import Callable, Dict, List, Mapping, Optional, Set, Tuple -from mypy.backports import OrderedDict from mypyc.codegen.emit import Emitter, HeaderDeclaration, ReturnHandler from mypyc.codegen.emitfunc import native_function_header from mypyc.codegen.emitwrapper import ( @@ -141,7 +140,7 @@ def slot_key(attr: str) -> str: def generate_slots(cl: ClassIR, table: SlotTable, emitter: Emitter) -> Dict[str, str]: - fields: Dict[str, str] = OrderedDict() + fields: Dict[str, str] = {} generated: Dict[str, str] = {} # Sort for determinism on Python 3.5 for name, (slot, generator) in sorted(table.items(), key=lambda x: slot_key(x[0])): @@ -199,7 +198,7 @@ def generate_class(cl: ClassIR, module: str, emitter: Emitter) -> None: methods_name = f"{name_prefix}_methods" vtable_setup_name = f"{name_prefix}_trait_vtable_setup" - fields: Dict[str, str] = OrderedDict() + fields: Dict[str, str] = {} fields["tp_name"] = f'"{name}"' generate_full = not cl.is_trait and not cl.builtin_base diff --git a/mypyc/codegen/emitmodule.py b/mypyc/codegen/emitmodule.py index d16e0a74b792..628820b9db45 100644 --- a/mypyc/codegen/emitmodule.py +++ b/mypyc/codegen/emitmodule.py @@ -7,7 +7,6 @@ import os from typing import Dict, Iterable, List, Optional, Set, Tuple, TypeVar -from mypy.backports import OrderedDict from mypy.build import ( BuildResult, BuildSource, @@ -976,7 +975,7 @@ def toposort_declarations(self) -> List[HeaderDeclaration]: This runs in O(V + E). """ result = [] - marked_declarations: Dict[str, MarkedDeclaration] = OrderedDict() + marked_declarations: Dict[str, MarkedDeclaration] = {} for k, v in self.context.declarations.items(): marked_declarations[k] = MarkedDeclaration(v, False) @@ -1063,7 +1062,7 @@ def declare_static_pyobject(self, identifier: str, emitter: Emitter) -> None: def sort_classes(classes: List[Tuple[str, ClassIR]]) -> List[Tuple[str, ClassIR]]: mod_name = {ir: name for name, ir in classes} irs = [ir for _, ir in classes] - deps: Dict[ClassIR, Set[ClassIR]] = OrderedDict() + deps: Dict[ClassIR, Set[ClassIR]] = {} for ir in irs: if ir not in deps: deps[ir] = set() diff --git a/mypyc/ir/class_ir.py b/mypyc/ir/class_ir.py index 015fd503ffc7..8158c917755b 100644 --- a/mypyc/ir/class_ir.py +++ b/mypyc/ir/class_ir.py @@ -2,7 +2,6 @@ from typing import Dict, List, NamedTuple, Optional, Set, Tuple -from mypy.backports import OrderedDict from mypyc.common import PROPSET_PREFIX, JsonDict from mypyc.ir.func_ir import FuncDecl, FuncIR, FuncSignature from mypyc.ir.ops import DeserMaps, Value @@ -129,32 +128,32 @@ def __init__( # Default empty constructor self.ctor = FuncDecl(name, None, module_name, FuncSignature([], RInstance(self))) - self.attributes: OrderedDict[str, RType] = OrderedDict() + self.attributes: Dict[str, RType] = {} # Deletable attributes self.deletable: List[str] = [] # We populate method_types with the signatures of every method before # we generate methods, and we rely on this information being present. - self.method_decls: OrderedDict[str, FuncDecl] = OrderedDict() + self.method_decls: Dict[str, FuncDecl] = {} # Map of methods that are actually present in an extension class - self.methods: OrderedDict[str, FuncIR] = OrderedDict() + self.methods: Dict[str, FuncIR] = {} # Glue methods for boxing/unboxing when a class changes the type # while overriding a method. Maps from (parent class overridden, method) # to IR of glue method. - self.glue_methods: Dict[Tuple[ClassIR, str], FuncIR] = OrderedDict() + self.glue_methods: Dict[Tuple[ClassIR, str], FuncIR] = {} # Properties are accessed like attributes, but have behavior like method calls. # They don't belong in the methods dictionary, since we don't want to expose them to # Python's method API. But we want to put them into our own vtable as methods, so that # they are properly handled and overridden. The property dictionary values are a tuple # containing a property getter and an optional property setter. - self.properties: OrderedDict[str, Tuple[FuncIR, Optional[FuncIR]]] = OrderedDict() + self.properties: Dict[str, Tuple[FuncIR, Optional[FuncIR]]] = {} # We generate these in prepare_class_def so that we have access to them when generating # other methods and properties that rely on these types. - self.property_types: OrderedDict[str, RType] = OrderedDict() + self.property_types: Dict[str, RType] = {} self.vtable: Optional[Dict[str, int]] = None self.vtable_entries: VTableEntries = [] - self.trait_vtables: OrderedDict[ClassIR, VTableEntries] = OrderedDict() + self.trait_vtables: Dict[ClassIR, VTableEntries] = {} # N.B: base might not actually quite be the direct base. # It is the nearest concrete base, but we allow a trait in between. self.base: Optional[ClassIR] = None @@ -388,27 +387,25 @@ def deserialize(cls, data: JsonDict, ctx: "DeserMaps") -> "ClassIR": ir._serializable = data["_serializable"] ir.builtin_base = data["builtin_base"] ir.ctor = FuncDecl.deserialize(data["ctor"], ctx) - ir.attributes = OrderedDict((k, deserialize_type(t, ctx)) for k, t in data["attributes"]) - ir.method_decls = OrderedDict( - (k, ctx.functions[v].decl if isinstance(v, str) else FuncDecl.deserialize(v, ctx)) + ir.attributes = {k: deserialize_type(t, ctx) for k, t in data["attributes"]} + ir.method_decls = { + k: ctx.functions[v].decl if isinstance(v, str) else FuncDecl.deserialize(v, ctx) for k, v in data["method_decls"] - ) - ir.methods = OrderedDict((k, ctx.functions[v]) for k, v in data["methods"]) - ir.glue_methods = OrderedDict( - ((ctx.classes[c], k), ctx.functions[v]) for (c, k), v in data["glue_methods"] - ) - ir.property_types = OrderedDict( - (k, deserialize_type(t, ctx)) for k, t in data["property_types"] - ) - ir.properties = OrderedDict( - (k, (ir.methods[k], ir.methods.get(PROPSET_PREFIX + k))) for k in data["properties"] - ) + } + ir.methods = {k: ctx.functions[v] for k, v in data["methods"]} + ir.glue_methods = { + (ctx.classes[c], k): ctx.functions[v] for (c, k), v in data["glue_methods"] + } + ir.property_types = {k: deserialize_type(t, ctx) for k, t in data["property_types"]} + ir.properties = { + k: (ir.methods[k], ir.methods.get(PROPSET_PREFIX + k)) for k in data["properties"] + } ir.vtable = data["vtable"] ir.vtable_entries = deserialize_vtable(data["vtable_entries"], ctx) - ir.trait_vtables = OrderedDict( - (ctx.classes[k], deserialize_vtable(v, ctx)) for k, v in data["trait_vtables"] - ) + ir.trait_vtables = { + ctx.classes[k]: deserialize_vtable(v, ctx) for k, v in data["trait_vtables"] + } base = data["base"] ir.base = ctx.classes[base] if base else None diff --git a/mypyc/ir/ops.py b/mypyc/ir/ops.py index dec4018a14cb..f8015f99e898 100644 --- a/mypyc/ir/ops.py +++ b/mypyc/ir/ops.py @@ -375,7 +375,7 @@ def set_target(self, i: int, new: BasicBlock) -> None: assert i == 0 or i == 1 if i == 0: self.true = new - elif i == 1: + else: self.false = new def sources(self) -> List[Value]: diff --git a/mypyc/irbuild/builder.py b/mypyc/irbuild/builder.py index d62c1700c78a..25fd33c03391 100644 --- a/mypyc/irbuild/builder.py +++ b/mypyc/irbuild/builder.py @@ -15,7 +15,6 @@ from typing_extensions import Final, overload -from mypy.backports import OrderedDict from mypy.build import Graph from mypy.maptype import map_instance_to_supertype from mypy.nodes import ( @@ -148,7 +147,7 @@ def __init__( ) -> None: self.builder = LowLevelIRBuilder(current_module, mapper, options) self.builders = [self.builder] - self.symtables: List[OrderedDict[SymbolNode, SymbolTarget]] = [OrderedDict()] + self.symtables: List[Dict[SymbolNode, SymbolTarget]] = [{}] self.runtime_args: List[List[RuntimeArg]] = [[]] self.function_name_stack: List[str] = [] self.class_ir_stack: List[ClassIR] = [] @@ -196,7 +195,7 @@ def __init__( # Notionally a list of all of the modules imported by the # module being compiled, but stored as an OrderedDict so we # can also do quick lookups. - self.imports: OrderedDict[str, None] = OrderedDict() + self.imports: Dict[str, None] = {} self.can_borrow = False @@ -1037,7 +1036,7 @@ def enter(self, fn_info: Union[FuncInfo, str] = "") -> None: fn_info = FuncInfo(name=fn_info) self.builder = LowLevelIRBuilder(self.current_module, self.mapper, self.options) self.builders.append(self.builder) - self.symtables.append(OrderedDict()) + self.symtables.append({}) self.runtime_args.append([]) self.fn_info = fn_info self.fn_infos.append(self.fn_info) diff --git a/mypyc/irbuild/function.py b/mypyc/irbuild/function.py index f6e5854f1e5b..21b6f23e9ac3 100644 --- a/mypyc/irbuild/function.py +++ b/mypyc/irbuild/function.py @@ -129,7 +129,6 @@ def transform_decorator(builder: IRBuilder, dec: Decorator) -> None: if func_reg: decorated_func = load_decorated_func(builder, dec.func, func_reg) builder.assign(get_func_target(builder, dec.func), decorated_func, dec.func.line) - func_reg = decorated_func # If the prebuild pass didn't put this function in the function to decorators map (for example # if this is a registered singledispatch implementation with no other decorators), we should # treat this function as a regular function, not a decorated function diff --git a/mypyc/irbuild/main.py b/mypyc/irbuild/main.py index 29df7f173424..227fa024d20c 100644 --- a/mypyc/irbuild/main.py +++ b/mypyc/irbuild/main.py @@ -22,7 +22,6 @@ def f(x: int) -> int: from typing import Any, Callable, Dict, List, TypeVar, cast -from mypy.backports import OrderedDict from mypy.build import Graph from mypy.nodes import ClassDef, Expression, MypyFile from mypy.state import state @@ -61,7 +60,7 @@ def build_ir( build_type_map(mapper, modules, graph, types, options, errors) singledispatch_info = find_singledispatch_register_impls(modules, errors) - result: ModuleIRs = OrderedDict() + result: ModuleIRs = {} # Generate IR for all modules. class_irs = [] diff --git a/mypyc/irbuild/mapper.py b/mypyc/irbuild/mapper.py index e86c99f51e69..d3813fac1438 100644 --- a/mypyc/irbuild/mapper.py +++ b/mypyc/irbuild/mapper.py @@ -154,7 +154,7 @@ def fdef_to_sig(self, fdef: FuncDef) -> FuncSignature: ret = self.type_to_rtype(fdef.type.ret_type) else: # Handle unannotated functions - arg_types = [object_rprimitive for arg in fdef.arguments] + arg_types = [object_rprimitive for _ in fdef.arguments] arg_pos_onlys = [arg.pos_only for arg in fdef.arguments] # We at least know the return type for __init__ methods will be None. is_init_method = fdef.name == "__init__" and bool(fdef.info) diff --git a/mypyc/test/test_emitfunc.py b/mypyc/test/test_emitfunc.py index 9f2b7516e2da..7511ad297f67 100644 --- a/mypyc/test/test_emitfunc.py +++ b/mypyc/test/test_emitfunc.py @@ -1,7 +1,6 @@ import unittest from typing import List, Optional -from mypy.backports import OrderedDict from mypy.test.helpers import assert_string_arrays_equal from mypyc.codegen.emit import Emitter, EmitterContext from mypyc.codegen.emitfunc import FunctionEmitterVisitor, generate_native_function @@ -103,7 +102,7 @@ def add_local(name: str, rtype: RType) -> Register: "tt", RTuple([RTuple([int_rprimitive, bool_rprimitive]), bool_rprimitive]) ) ir = ClassIR("A", "mod") - ir.attributes = OrderedDict([("x", bool_rprimitive), ("y", int_rprimitive)]) + ir.attributes = {"x": bool_rprimitive, "y": int_rprimitive} compute_vtable(ir) ir.mro = [ir] self.r = add_local("r", RInstance(ir)) diff --git a/mypyc/test/test_serialization.py b/mypyc/test/test_serialization.py index 1c54b4ae074a..285c6edd991f 100644 --- a/mypyc/test/test_serialization.py +++ b/mypyc/test/test_serialization.py @@ -6,7 +6,6 @@ from collections.abc import Iterable from typing import Any, Dict, Tuple -from mypy.backports import OrderedDict from mypyc.ir.class_ir import ClassIR from mypyc.ir.func_ir import FuncDecl, FuncIR, FuncSignature from mypyc.ir.module_ir import ModuleIR, deserialize_modules @@ -49,7 +48,7 @@ def assert_blobs_same(x: Any, y: Any, trail: Tuple[Any, ...]) -> None: assert type(x) is type(y), (f"Type mismatch at {trail}", type(x), type(y)) if isinstance(x, (FuncDecl, FuncIR, ClassIR)): assert x.fullname == y.fullname, f"Name mismatch at {trail}" - elif isinstance(x, OrderedDict): + elif isinstance(x, dict): assert len(x.keys()) == len(y.keys()), f"Keys mismatch at {trail}" for (xk, xv), (yk, yv) in zip(x.items(), y.items()): assert_blobs_same(xk, yk, trail + ("keys",)) diff --git a/mypyc/transform/refcount.py b/mypyc/transform/refcount.py index 05e2843fe886..6d3f1e509246 100644 --- a/mypyc/transform/refcount.py +++ b/mypyc/transform/refcount.py @@ -119,8 +119,8 @@ def transform_block( # Incref any references that are being stolen that stay live, were borrowed, # or are stolen more than once by this operation. - for i, src in enumerate(stolen): - if src in post_live[key] or src in pre_borrow[key] or src in stolen[:i]: + for j, src in enumerate(stolen): + if src in post_live[key] or src in pre_borrow[key] or src in stolen[:j]: maybe_append_inc_ref(ops, src) # For assignments to registers that were already live, # decref the old value.