From 246e601383dd84e28a544f7658346e96edc70441 Mon Sep 17 00:00:00 2001 From: Ilya Priven Date: Sat, 2 Sep 2023 17:08:10 -0400 Subject: [PATCH 1/8] ruff: enable pyupgrade --- mypy/checkmember.py | 4 ++-- mypyc/ir/class_ir.py | 2 +- mypyc/ir/ops.py | 4 ++-- mypyc/ir/rtypes.py | 4 ++-- pyproject.toml | 6 +++++- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/mypy/checkmember.py b/mypy/checkmember.py index f7d002f17eb9..60430839ff62 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Callable, Optional, Sequence, cast +from typing import TYPE_CHECKING, Callable, Sequence, cast from mypy import meet, message_registry, subtypes from mypy.erasetype import erase_typevars @@ -777,7 +777,7 @@ def analyze_var( result: Type = t typ = get_proper_type(typ) - call_type: Optional[ProperType] = None + call_type: ProperType | None = None if var.is_initialized_in_class and (not is_instance_var(var) or mx.is_operator): if isinstance(typ, FunctionLike) and not typ.is_type_obj(): call_type = typ diff --git a/mypyc/ir/class_ir.py b/mypyc/ir/class_ir.py index 682e30629118..a577990688b0 100644 --- a/mypyc/ir/class_ir.py +++ b/mypyc/ir/class_ir.py @@ -70,7 +70,7 @@ class VTableMethod(NamedTuple): - cls: "ClassIR" + cls: ClassIR name: str method: FuncIR shadow_method: FuncIR | None diff --git a/mypyc/ir/ops.py b/mypyc/ir/ops.py index d80c479211b7..2d64cc79d822 100644 --- a/mypyc/ir/ops.py +++ b/mypyc/ir/ops.py @@ -1575,5 +1575,5 @@ def visit_keep_alive(self, op: KeepAlive) -> T: # (Serialization and deserialization *will* be used for incremental # compilation but so far it is not hooked up to anything.) class DeserMaps(NamedTuple): - classes: dict[str, "ClassIR"] - functions: dict[str, "FuncIR"] + classes: dict[str, ClassIR] + functions: dict[str, FuncIR] diff --git a/mypyc/ir/rtypes.py b/mypyc/ir/rtypes.py index fa46feb0b59a..fecfaee5ef77 100644 --- a/mypyc/ir/rtypes.py +++ b/mypyc/ir/rtypes.py @@ -23,8 +23,8 @@ from __future__ import annotations from abc import abstractmethod -from typing import TYPE_CHECKING, ClassVar, Generic, TypeVar -from typing_extensions import Final, TypeGuard +from typing import TYPE_CHECKING, ClassVar, Final, Generic, TypeVar +from typing_extensions import TypeGuard from mypyc.common import IS_32_BIT_PLATFORM, PLATFORM_SIZE, JsonDict, short_name from mypyc.namegen import NameGenerator diff --git a/pyproject.toml b/pyproject.toml index 67201acb9b94..e2f4cf05790b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,7 +36,8 @@ select = [ "B", # flake8-bugbear "I", # isort "RUF100", # Unused noqa comments - "PGH004" # blanket noqa comments + "PGH004", # blanket noqa comments + "UP", # pyupgrade ] ignore = [ @@ -49,6 +50,9 @@ ignore = [ "E501", # conflicts with black "E731", # Do not assign a `lambda` expression, use a `def` "E741", # Ambiguous variable name + "UP006", + "UP031", + "UP032", ] unfixable = [ From b51531f034a4b8455c5f8d96451328a683b76f90 Mon Sep 17 00:00:00 2001 From: Ilya Priven Date: Sat, 2 Sep 2023 17:08:52 -0400 Subject: [PATCH 2/8] enable UP006 --- mypy/solve.py | 4 ++-- pyproject.toml | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/mypy/solve.py b/mypy/solve.py index 95377ea9f93e..17e1ca047818 100644 --- a/mypy/solve.py +++ b/mypy/solve.py @@ -3,7 +3,7 @@ from __future__ import annotations from collections import defaultdict -from typing import Iterable, Sequence, Tuple +from typing import Iterable, Sequence from typing_extensions import TypeAlias as _TypeAlias from mypy.constraints import SUBTYPE_OF, SUPERTYPE_OF, Constraint, infer_constraints @@ -333,7 +333,7 @@ def is_trivial_bound(tp: ProperType) -> bool: return isinstance(tp, Instance) and tp.type.fullname == "builtins.object" -def find_linear(c: Constraint) -> Tuple[bool, TypeVarId | None]: +def find_linear(c: Constraint) -> tuple[bool, TypeVarId | None]: """Find out if this constraint represent a linear relationship, return target id if yes.""" if isinstance(c.origin_type_var, TypeVarType): if isinstance(c.target, TypeVarType): diff --git a/pyproject.toml b/pyproject.toml index e2f4cf05790b..21ac776c8c7c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,7 +50,6 @@ ignore = [ "E501", # conflicts with black "E731", # Do not assign a `lambda` expression, use a `def` "E741", # Ambiguous variable name - "UP006", "UP031", "UP032", ] From 56a82e9a3e9ca558316cad51bea90a380d008ce5 Mon Sep 17 00:00:00 2001 From: Ilya Priven Date: Sat, 2 Sep 2023 17:18:30 -0400 Subject: [PATCH 3/8] UP031 --- mypy/config_parser.py | 17 +++++++++-------- mypy/main.py | 3 +-- mypy/messages.py | 13 ++++++------- pyproject.toml | 1 - 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/mypy/config_parser.py b/mypy/config_parser.py index 7748c3b25966..cfa38e3ca7ed 100644 --- a/mypy/config_parser.py +++ b/mypy/config_parser.py @@ -291,15 +291,15 @@ def parse_config_file( prefix, options, set_strict_flags, section, config_types, stderr ) if report_dirs: + reports = ", ".join(f"{s}_report" for s in sorted(report_dirs)) print( - "%sPer-module sections should not specify reports (%s)" - % (prefix, ", ".join(s + "_report" for s in sorted(report_dirs))), + f"{prefix}Per-module sections should not specify reports ({reports})", file=stderr, ) if set(updates) - PER_MODULE_OPTIONS: + flags = ", ".join(sorted(set(updates) - PER_MODULE_OPTIONS)) print( - "%sPer-module sections should only specify per-module flags (%s)" - % (prefix, ", ".join(sorted(set(updates) - PER_MODULE_OPTIONS))), + f"{prefix}Per-module sections should only specify per-module flags ({flags})", file=stderr, ) updates = {k: v for k, v in updates.items() if k in PER_MODULE_OPTIONS} @@ -315,8 +315,8 @@ def parse_config_file( "*" in x and x != "*" for x in glob.split(".") ): print( - "%sPatterns must be fully-qualified module names, optionally " - "with '*' in some components (e.g spam.*.eggs.*)" % prefix, + f"{prefix}Patterns must be fully-qualified module names, optionally " + "with '*' in some components (e.g spam.*.eggs.*)", file=stderr, ) else: @@ -411,8 +411,9 @@ def destructure_overrides(toml_data: dict[str, Any]) -> dict[str, Any]: raise ConfigTOMLValueError( "toml config file contains " "[[tool.mypy.overrides]] sections with conflicting " - "values. Module '%s' has two different values for '%s'" - % (module, new_key) + "values. Module '{}' has two different values for '{}'".format( + module, new_key + ) ) result[old_config_name][new_key] = new_value diff --git a/mypy/main.py b/mypy/main.py index 30f6cfe97455..a4357dca7890 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -187,8 +187,7 @@ def flush_errors(new_messages: list[str], serious: bool) -> None: and not options.non_interactive ): print( - "Warning: unused section(s) in %s: %s" - % ( + "Warning: unused section(s) in {}: {}".format( options.config_file, get_config_module_names( options.config_file, diff --git a/mypy/messages.py b/mypy/messages.py index 4b71bd876dcc..6f9c960cdcd2 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -1454,19 +1454,18 @@ def cannot_determine_type_in_base(self, name: str, base: str, context: Context) self.fail(f'Cannot determine type of "{name}" in base class "{base}"', context) def no_formal_self(self, name: str, item: CallableType, context: Context) -> None: + type = format_type(item, self.options) self.fail( - 'Attribute function "%s" with type %s does not accept self argument' - % (name, format_type(item, self.options)), - context, + f"Attribute function {name!r} with type {type} does not accept self argument", context ) def incompatible_self_argument( self, name: str, arg: Type, sig: CallableType, is_classmethod: bool, context: Context ) -> None: kind = "class attribute function" if is_classmethod else "attribute function" + type = format_type(sig, self.options) self.fail( - 'Invalid self argument %s to %s "%s" with type %s' - % (format_type(arg, self.options), kind, name, format_type(sig, self.options)), + f"Invalid self argument {format_type(arg, self.options)} to {kind} {name!r} with type {type}", context, ) @@ -1487,8 +1486,8 @@ def cannot_instantiate_abstract_class( ) -> None: attrs = format_string_list([f'"{a}"' for a in abstract_attributes]) self.fail( - 'Cannot instantiate abstract class "%s" with abstract ' - "attribute%s %s" % (class_name, plural_s(abstract_attributes), attrs), + f"Cannot instantiate abstract class {class_name!r} with abstract " + f"attribute{plural_s(abstract_attributes)} {attrs}", context, code=codes.ABSTRACT, ) diff --git a/pyproject.toml b/pyproject.toml index 21ac776c8c7c..0637e8be93f8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,7 +50,6 @@ ignore = [ "E501", # conflicts with black "E731", # Do not assign a `lambda` expression, use a `def` "E741", # Ambiguous variable name - "UP031", "UP032", ] From c4c81bd9b17b42a73dc6fafed694a401a3d17931 Mon Sep 17 00:00:00 2001 From: Ilya Priven Date: Sat, 2 Sep 2023 17:19:59 -0400 Subject: [PATCH 4/8] clarify --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 0637e8be93f8..18ba23671d9c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,7 +50,7 @@ ignore = [ "E501", # conflicts with black "E731", # Do not assign a `lambda` expression, use a `def` "E741", # Ambiguous variable name - "UP032", + "UP032", # 'f-string always preferable to format' is controversial ] unfixable = [ From 8ccd3b2e49a13d90653636297645fcaf51d37d08 Mon Sep 17 00:00:00 2001 From: Ilya Priven Date: Sat, 2 Sep 2023 19:29:36 -0400 Subject: [PATCH 5/8] Revert "UP031" This reverts commit 56a82e9a3e9ca558316cad51bea90a380d008ce5. --- mypy/config_parser.py | 17 ++++++++--------- mypy/main.py | 3 ++- mypy/messages.py | 13 +++++++------ pyproject.toml | 1 + 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/mypy/config_parser.py b/mypy/config_parser.py index cfa38e3ca7ed..7748c3b25966 100644 --- a/mypy/config_parser.py +++ b/mypy/config_parser.py @@ -291,15 +291,15 @@ def parse_config_file( prefix, options, set_strict_flags, section, config_types, stderr ) if report_dirs: - reports = ", ".join(f"{s}_report" for s in sorted(report_dirs)) print( - f"{prefix}Per-module sections should not specify reports ({reports})", + "%sPer-module sections should not specify reports (%s)" + % (prefix, ", ".join(s + "_report" for s in sorted(report_dirs))), file=stderr, ) if set(updates) - PER_MODULE_OPTIONS: - flags = ", ".join(sorted(set(updates) - PER_MODULE_OPTIONS)) print( - f"{prefix}Per-module sections should only specify per-module flags ({flags})", + "%sPer-module sections should only specify per-module flags (%s)" + % (prefix, ", ".join(sorted(set(updates) - PER_MODULE_OPTIONS))), file=stderr, ) updates = {k: v for k, v in updates.items() if k in PER_MODULE_OPTIONS} @@ -315,8 +315,8 @@ def parse_config_file( "*" in x and x != "*" for x in glob.split(".") ): print( - f"{prefix}Patterns must be fully-qualified module names, optionally " - "with '*' in some components (e.g spam.*.eggs.*)", + "%sPatterns must be fully-qualified module names, optionally " + "with '*' in some components (e.g spam.*.eggs.*)" % prefix, file=stderr, ) else: @@ -411,9 +411,8 @@ def destructure_overrides(toml_data: dict[str, Any]) -> dict[str, Any]: raise ConfigTOMLValueError( "toml config file contains " "[[tool.mypy.overrides]] sections with conflicting " - "values. Module '{}' has two different values for '{}'".format( - module, new_key - ) + "values. Module '%s' has two different values for '%s'" + % (module, new_key) ) result[old_config_name][new_key] = new_value diff --git a/mypy/main.py b/mypy/main.py index a4357dca7890..30f6cfe97455 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -187,7 +187,8 @@ def flush_errors(new_messages: list[str], serious: bool) -> None: and not options.non_interactive ): print( - "Warning: unused section(s) in {}: {}".format( + "Warning: unused section(s) in %s: %s" + % ( options.config_file, get_config_module_names( options.config_file, diff --git a/mypy/messages.py b/mypy/messages.py index 6f9c960cdcd2..4b71bd876dcc 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -1454,18 +1454,19 @@ def cannot_determine_type_in_base(self, name: str, base: str, context: Context) self.fail(f'Cannot determine type of "{name}" in base class "{base}"', context) def no_formal_self(self, name: str, item: CallableType, context: Context) -> None: - type = format_type(item, self.options) self.fail( - f"Attribute function {name!r} with type {type} does not accept self argument", context + 'Attribute function "%s" with type %s does not accept self argument' + % (name, format_type(item, self.options)), + context, ) def incompatible_self_argument( self, name: str, arg: Type, sig: CallableType, is_classmethod: bool, context: Context ) -> None: kind = "class attribute function" if is_classmethod else "attribute function" - type = format_type(sig, self.options) self.fail( - f"Invalid self argument {format_type(arg, self.options)} to {kind} {name!r} with type {type}", + 'Invalid self argument %s to %s "%s" with type %s' + % (format_type(arg, self.options), kind, name, format_type(sig, self.options)), context, ) @@ -1486,8 +1487,8 @@ def cannot_instantiate_abstract_class( ) -> None: attrs = format_string_list([f'"{a}"' for a in abstract_attributes]) self.fail( - f"Cannot instantiate abstract class {class_name!r} with abstract " - f"attribute{plural_s(abstract_attributes)} {attrs}", + 'Cannot instantiate abstract class "%s" with abstract ' + "attribute%s %s" % (class_name, plural_s(abstract_attributes), attrs), context, code=codes.ABSTRACT, ) diff --git a/pyproject.toml b/pyproject.toml index 18ba23671d9c..a71f3c28c9e2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,6 +50,7 @@ ignore = [ "E501", # conflicts with black "E731", # Do not assign a `lambda` expression, use a `def` "E741", # Ambiguous variable name + "UP031", "UP032", # 'f-string always preferable to format' is controversial ] From a292d8f39696c5330fd1eece0ef202021e5f5ff9 Mon Sep 17 00:00:00 2001 From: Ilya Priven Date: Sat, 2 Sep 2023 19:38:08 -0400 Subject: [PATCH 6/8] try again --- mypy/config_parser.py | 24 +++++++++++++++--------- mypy/main.py | 3 +-- mypy/messages.py | 15 +++++++-------- pyproject.toml | 1 - 4 files changed, 23 insertions(+), 20 deletions(-) diff --git a/mypy/config_parser.py b/mypy/config_parser.py index 7748c3b25966..d8d5ec35d95a 100644 --- a/mypy/config_parser.py +++ b/mypy/config_parser.py @@ -292,14 +292,18 @@ def parse_config_file( ) if report_dirs: print( - "%sPer-module sections should not specify reports (%s)" - % (prefix, ", ".join(s + "_report" for s in sorted(report_dirs))), + prefix, + "Per-module sections should not specify reports ({})".format( + ", ".join(s + "_report" for s in sorted(report_dirs)) + ), file=stderr, ) if set(updates) - PER_MODULE_OPTIONS: print( - "%sPer-module sections should only specify per-module flags (%s)" - % (prefix, ", ".join(sorted(set(updates) - PER_MODULE_OPTIONS))), + prefix, + "Per-module sections should only specify per-module flags ({})".format( + ", ".join(sorted(set(updates) - PER_MODULE_OPTIONS)) + ), file=stderr, ) updates = {k: v for k, v in updates.items() if k in PER_MODULE_OPTIONS} @@ -315,8 +319,9 @@ def parse_config_file( "*" in x and x != "*" for x in glob.split(".") ): print( - "%sPatterns must be fully-qualified module names, optionally " - "with '*' in some components (e.g spam.*.eggs.*)" % prefix, + prefix, + "Patterns must be fully-qualified module names, optionally " + "with '*' in some components (e.g spam.*.eggs.*)", file=stderr, ) else: @@ -329,7 +334,7 @@ def get_prefix(file_read: str, name: str) -> str: else: module_name_str = name - return f"{file_read}: [{module_name_str}]: " + return f"{file_read}: [{module_name_str}]:" def is_toml(filename: str) -> bool: @@ -411,8 +416,9 @@ def destructure_overrides(toml_data: dict[str, Any]) -> dict[str, Any]: raise ConfigTOMLValueError( "toml config file contains " "[[tool.mypy.overrides]] sections with conflicting " - "values. Module '%s' has two different values for '%s'" - % (module, new_key) + "values. Module '{}' has two different values for '{}'".format( + module, new_key + ) ) result[old_config_name][new_key] = new_value diff --git a/mypy/main.py b/mypy/main.py index 30f6cfe97455..a4357dca7890 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -187,8 +187,7 @@ def flush_errors(new_messages: list[str], serious: bool) -> None: and not options.non_interactive ): print( - "Warning: unused section(s) in %s: %s" - % ( + "Warning: unused section(s) in {}: {}".format( options.config_file, get_config_module_names( options.config_file, diff --git a/mypy/messages.py b/mypy/messages.py index 4b71bd876dcc..bba9c3c3cdea 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -1454,20 +1454,19 @@ def cannot_determine_type_in_base(self, name: str, base: str, context: Context) self.fail(f'Cannot determine type of "{name}" in base class "{base}"', context) def no_formal_self(self, name: str, item: CallableType, context: Context) -> None: + type = format_type(item, self.options) self.fail( - 'Attribute function "%s" with type %s does not accept self argument' - % (name, format_type(item, self.options)), - context, + f'Attribute function "{name}" with type {type} does not accept self argument', context ) def incompatible_self_argument( self, name: str, arg: Type, sig: CallableType, is_classmethod: bool, context: Context ) -> None: kind = "class attribute function" if is_classmethod else "attribute function" + arg_type = format_type(arg, self.options) + sig_type = format_type(sig, self.options) self.fail( - 'Invalid self argument %s to %s "%s" with type %s' - % (format_type(arg, self.options), kind, name, format_type(sig, self.options)), - context, + f'Invalid self argument {arg_type} to {kind} "{name}" with type {sig_type}', context ) def incompatible_conditional_function_def( @@ -1487,8 +1486,8 @@ def cannot_instantiate_abstract_class( ) -> None: attrs = format_string_list([f'"{a}"' for a in abstract_attributes]) self.fail( - 'Cannot instantiate abstract class "%s" with abstract ' - "attribute%s %s" % (class_name, plural_s(abstract_attributes), attrs), + f'Cannot instantiate abstract class "{class_name}" with abstract ' + f"attribute{plural_s(abstract_attributes)} {attrs}", context, code=codes.ABSTRACT, ) diff --git a/pyproject.toml b/pyproject.toml index a71f3c28c9e2..18ba23671d9c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,7 +50,6 @@ ignore = [ "E501", # conflicts with black "E731", # Do not assign a `lambda` expression, use a `def` "E741", # Ambiguous variable name - "UP031", "UP032", # 'f-string always preferable to format' is controversial ] From b447c1c5b080ee7ea9f9779dba9405999dc38b0b Mon Sep 17 00:00:00 2001 From: Ilya Priven Date: Sat, 2 Sep 2023 22:00:27 -0400 Subject: [PATCH 7/8] nit --- mypy/config_parser.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mypy/config_parser.py b/mypy/config_parser.py index d8d5ec35d95a..4dbd6477c81e 100644 --- a/mypy/config_parser.py +++ b/mypy/config_parser.py @@ -416,9 +416,7 @@ def destructure_overrides(toml_data: dict[str, Any]) -> dict[str, Any]: raise ConfigTOMLValueError( "toml config file contains " "[[tool.mypy.overrides]] sections with conflicting " - "values. Module '{}' has two different values for '{}'".format( - module, new_key - ) + f"values. Module '{module}' has two different values for '{new_key}'" ) result[old_config_name][new_key] = new_value From 8d73ccd6a56b98566389facbf6b91002583003ee Mon Sep 17 00:00:00 2001 From: Ilya Priven Date: Sat, 2 Sep 2023 22:09:50 -0400 Subject: [PATCH 8/8] exempt from UP037 --- mypyc/ir/class_ir.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypyc/ir/class_ir.py b/mypyc/ir/class_ir.py index a577990688b0..61f0fc36e1b3 100644 --- a/mypyc/ir/class_ir.py +++ b/mypyc/ir/class_ir.py @@ -70,7 +70,7 @@ class VTableMethod(NamedTuple): - cls: ClassIR + cls: "ClassIR" # noqa: UP037 name: str method: FuncIR shadow_method: FuncIR | None